#!/bin/sh /etc/rc.common
# Copyright (c) 2019 vernesong

START=99
STOP=15

. $IPKG_INSTROOT/usr/share/openclash/openclash_ps.sh
. $IPKG_INSTROOT/usr/share/openclash/ruby.sh
. $IPKG_INSTROOT/usr/share/openclash/log.sh

[ -f /etc/openwrt_release ] && {
RAW_CONFIG_FILE=$(uci -q get openclash.config.config_path)
BACKUP_FILE="/etc/openclash/backup/$(uci -q get openclash.config.config_path |awk -F '/' '{print $5}' 2>/dev/null)"
CONFIG_FILE="/etc/openclash/$(uci -q get openclash.config.config_path |awk -F '/' '{print $5}' 2>/dev/null)"
TMP_CONFIG_FILE="/tmp/yaml_config_tmp_$(uci -q get openclash.config.config_path |awk -F '/' '{print $5}' 2>/dev/null)"
FW4=$(command -v fw4)
DNSMASQ_CONF_DIR=$(uci -q get dhcp.@dnsmasq[0].confdir || echo '/tmp/dnsmasq.d')
DNSMASQ_CONF_DIR=${DNSMASQ_CONF_DIR%*/}
}
LOGTIME=$(echo $(date "+%Y-%m-%d %H:%M:%S"))
CLASH="/etc/openclash/clash"
CLASH_CONFIG="/etc/openclash"
CRON_FILE="/etc/crontabs/root"
CACHE_PATH_OLD="/etc/openclash/.cache"
CACHE_PATH="/etc/openclash/cache.db"
LOG_FILE="/tmp/openclash.log"
START_LOG="/tmp/openclash_start.log"
LOCK_FILE="/tmp/lock/openclash.lock"
PROXY_FWMARK="0x162"
PROXY_ROUTE_TABLE="0x162"

set_lock() {
   exec 888>"$LOCK_FILE" 2>/dev/null
   flock -x 888 2>/dev/null
}

del_lock() {
   flock -u 888 2>/dev/null
   rm -rf "$LOCK_FILE"
}

add_cron()
{
   [ "$(tail -n1 /etc/crontabs/root | wc -l)" -eq 0 ] && [ -n "$(cat /etc/crontabs/root 2>/dev/null)" ] && echo >> /etc/crontabs/root
   [ -z "$(grep "openclash.sh" "$CRON_FILE" 2>/dev/null)" ] && {
      [ "$(uci -q get openclash.config.auto_update)" -eq 1 ] && [ "$(uci -q get openclash.config.config_auto_update_mode)" -ne 1 ] && echo "0 $(uci -q get openclash.config.auto_update_time) * * $(uci -q get openclash.config.config_update_week_time) /usr/share/openclash/openclash.sh" >> $CRON_FILE
   }
   [ -z "$(grep "openclash_rule.sh" "$CRON_FILE" 2>/dev/null)" ] && {
      [ "$(uci -q get openclash.config.other_rule_auto_update)" -eq 1 ] && echo "0 $(uci -q get openclash.config.other_rule_update_day_time) * * $(uci -q get openclash.config.other_rule_update_week_time) /usr/share/openclash/openclash_rule.sh" >> $CRON_FILE
   }
   [ -z "$(grep "openclash_ipdb.sh" "$CRON_FILE" 2>/dev/null)" ] && {
      [ "$(uci -q get openclash.config.geo_auto_update)" -eq 1 ] && echo "0 $(uci -q get openclash.config.geo_update_day_time) * * $(uci -q get openclash.config.geo_update_week_time) /usr/share/openclash/openclash_ipdb.sh" >> $CRON_FILE
   }
   [ -z "$(grep "openclash_geosite.sh" "$CRON_FILE" 2>/dev/null)" ] && {
      [ "$(uci -q get openclash.config.geosite_auto_update)" -eq 1 ] && echo "0 $(uci -q get openclash.config.geosite_update_day_time) * * $(uci -q get openclash.config.geosite_update_week_time) /usr/share/openclash/openclash_geosite.sh" >> $CRON_FILE
   }
   [ -z "$(grep "openclash_geoip.sh" "$CRON_FILE" 2>/dev/null)" ] && {
      [ "$(uci -q get openclash.config.geoip_auto_update)" -eq 1 ] && echo "0 $(uci -q get openclash.config.geoip_update_day_time) * * $(uci -q get openclash.config.geoip_update_week_time) /usr/share/openclash/openclash_geoip.sh" >> $CRON_FILE
   }
   [ -z "$(grep "openclash_chnroute.sh" "$CRON_FILE" 2>/dev/null)" ] && {
      [ "$(uci -q get openclash.config.chnr_auto_update)" -eq 1 ] && echo "0 $(uci -q get openclash.config.chnr_update_day_time) * * $(uci -q get openclash.config.chnr_update_week_time) /usr/share/openclash/openclash_chnroute.sh" >> $CRON_FILE
   }
   [ -z "$(grep "/etc/init.d/openclash" "$CRON_FILE" 2>/dev/null)" ] && {
      [ "$(uci -q get openclash.config.auto_restart)" -eq 1 ] && echo "0 $(uci -q get openclash.config.auto_restart_day_time) * * $(uci -q get openclash.config.auto_restart_week_time) /etc/init.d/openclash restart 2>/dev/null" >> $CRON_FILE
   }
   crontab $CRON_FILE
   nohup /usr/share/openclash/openclash_watchdog.sh &
}

del_cron()
{
   sed -i '/openclash.sh/d' $CRON_FILE 2>/dev/null
   sed -i '/openclash_rule.sh/d' $CRON_FILE 2>/dev/null
   sed -i '/openclash_ipdb.sh/d' $CRON_FILE 2>/dev/null
   sed -i '/openclash_geoip.sh/d' $CRON_FILE 2>/dev/null
   sed -i '/openclash_geosite.sh/d' $CRON_FILE 2>/dev/null
   sed -i '/openclash_chnroute.sh/d' $CRON_FILE 2>/dev/null
   sed -i '/\/etc\/init.d\/openclash/d' $CRON_FILE 2>/dev/null
   /etc/init.d/cron restart
}

save_dnsmasq_server() {
   if [ -z "$1" ] || [ "$1" == "127.0.0.1#${dns_port}" ]; then
     return
   fi

   uci -q add_list openclash.config.dnsmasq_server="$1"
}

set_dnsmasq_server() {
	if [ -z "$1" ] || [ "$1" == "127.0.0.1#${dns_port}" ]; then
     return
   fi

   uci -q add_list dhcp.@dnsmasq[0].server="$1"
}

change_dns() {
   if [ "$1" -eq 1 ]; then
      uci -q del openclash.config.dnsmasq_server
      config_load "dhcp"
      config_list_foreach "$(uci show dhcp.@dnsmasq[0].server |awk -F '.' '{print $2}')" "server" save_dnsmasq_server
      uci -q del dhcp.@dnsmasq[-1].server
      uci -q add_list dhcp.@dnsmasq[0].server=127.0.0.1#"$dns_port"
      uci -q set openclash.config.dnsmasq_noresolv="$(uci -q get dhcp.@dnsmasq[0].noresolv)"
      uci -q set openclash.config.dnsmasq_resolvfile="$(uci -q get dhcp.@dnsmasq[0].resolvfile)"
      uci -q delete dhcp.@dnsmasq[0].resolvfile
      uci -q set dhcp.@dnsmasq[0].noresolv=1
      uci -q set dhcp.@dnsmasq[0].localuse=1
      uci -q set openclash.config.redirect_dns=1
   else
      uci -q set openclash.config.redirect_dns=0
   fi

   if [ "$1" -eq 1 ] && [ "$2" -eq 1 ]; then
      uci -q set openclash.config.dnsmasq_cachesize="$(uci -q get dhcp.@dnsmasq[0].cachesize)"
      uci -q set dhcp.@dnsmasq[0].cachesize=0
      uci -q set openclash.config.cachesize_dns=1
   else
      uci -q set openclash.config.cachesize_dns=0
   fi

   if [ "$1" -eq 1 ] && [ "$ipv6_dns" -eq 1 ] && [ -n "$(ip6tables -t mangle -L 2>&1 | grep -o 'Chain')" ]; then
      #dnsmasq answer ipv6
      uci -q set openclash.config.dnsmasq_filter_aaaa="$(uci -q get dhcp.@dnsmasq[0].filter_aaaa)"
	   uci -q set dhcp.@dnsmasq[0].filter_aaaa=0
	   uci -q set openclash.config.filter_aaaa_dns=1
	else
	   uci -q set openclash.config.filter_aaaa_dns=0
	fi

   uci -q commit dhcp
   uci -q commit openclash
   /etc/init.d/dnsmasq restart >/dev/null 2>&1
}

revert_dns() {

   rm -rf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_custom_domain.conf >/dev/null 2>&1

   [ "$1" -eq 1 ] && {
      uci -q del dhcp.@dnsmasq[-1].server
      [ -n "${10}" ] && {
         config_load "openclash"
         config_list_foreach "config" "dnsmasq_server" set_dnsmasq_server
      }

      if [ "$4" == "0" ] || [ -z "$4" ] || [ -z "$(uci -q show dhcp.@dnsmasq[0].server)" ]; then
         uci -q set dhcp.@dnsmasq[0].noresolv=0
         if [ -n "$5" ] && [ -n "$(grep nameserver $5)" ]; then
            uci -q set dhcp.@dnsmasq[0].resolvfile="$5"
         elif [ -n "$3" ] && [ -n "$(grep nameserver $3)" ]; then
            uci -q set dhcp.@dnsmasq[0].resolvfile="$3"
         elif [ -s "/tmp/resolv.conf.d/resolv.conf.auto" ] && [ -n "$(grep "nameserver" /tmp/resolv.conf.d/resolv.conf.auto)" ]; then
            uci -q set dhcp.@dnsmasq[0].resolvfile=/tmp/resolv.conf.d/resolv.conf.auto
            uci -q set openclash.config.default_resolvfile=/tmp/resolv.conf.d/resolv.conf.auto
         elif [ -s "/tmp/resolv.conf.auto" ] && [ -n "$(grep "nameserver" /tmp/resolv.conf.auto)" ]; then
            uci -q set dhcp.@dnsmasq[0].resolvfile=/tmp/resolv.conf.auto
            uci -q set openclash.config.default_resolvfile=/tmp/resolv.conf.auto
         else
            uci -q set dhcp.@dnsmasq[0].resolvfile=/tmp/resolv.conf.d/resolv.conf.auto
            uci -q set openclash.config.default_resolvfile=/tmp/resolv.conf.d/resolv.conf.auto
         fi
         uci -q set dhcp.@dnsmasq[0].localuse=1
         uci -q commit dhcp
         /etc/init.d/dnsmasq restart >/dev/null 2>&1
         masq_port=$(uci -q get dhcp.@dnsmasq[0].port)
         if [ "$(nslookup www.apple.com 127.0.0.1:${masq_port} >/dev/null 2>&1 || echo $?)" = "1" ]; then
            uci -q set openclash.config.default_resolvfile="/tmp/resolv.conf.d/resolv.conf.auto"
            mkdir -p /tmp/resolv.conf.d
            rm -rf /tmp/resolv.conf.d/resolv.conf.auto
            touch /tmp/resolv.conf.d/resolv.conf.auto 2>/dev/null
            cat >> "/tmp/resolv.conf.d/resolv.conf.auto" <<-EOF
# Interface lan
nameserver 119.29.29.29
nameserver 8.8.8.8
EOF
            uci -q set dhcp.@dnsmasq[0].resolvfile="/tmp/resolv.conf.d/resolv.conf.auto"
         fi
      fi
   }

   [ "$6" -eq 1 ] && {
      uci -q set dhcp.@dnsmasq[0].cachesize="$7"
      uci -q set openclash.config.cachesize_dns=0
      uci -q delete openclash.config.dnsmasq_cachesize
   }

   [ "$8" -eq 1 ] && {
      uci -q set dhcp.@dnsmasq[0].filter_aaaa="$9"
      uci -q set openclash.config.filter_aaaa_dns=0
      uci -q delete openclash.config.dnsmasq_filter_aaaa
   }

   [ "$1" -eq 1 ] && {
      uci -q set openclash.config.redirect_dns=0
      uci -q del openclash.config.dnsmasq_server
   }

   uci -q commit dhcp
   uci -q commit openclash

}

kill_clash()
{
   clash_pids=$(pidof clash |sed 's/$//g')
   for clash_pid in $clash_pids; do
      kill -9 "$clash_pid" 2>/dev/null
   done >/dev/null 2>&1
   sleep 1
}

start_fail()
{
   kill_clash
   stop
   del_lock
   exit 0
}

#检查集文件防止启动失败
yml_provider_check()
{
provider_path_line=$(ruby_read "$1" ".key?('$2')")
local provider_path_check
if "$provider_path_line"; then
   while :;
   do
      provider_path_check=$(ruby -ryaml -rYAML -I "/usr/share/openclash" -E UTF-8 -e "
      Value = YAML.load_file('$1');
      Value['$2'].values.each{|x,v|
      if not x['path'].empty? then
         if x['path'].split('/')[0] == '.' then
            v = '/etc/openclash/'+x['path'].split('./')[1]
         else
            v = x['path']
         end
      end;
      if File::exist?(v) then
         if not YAML.load_file(v).key?('$3') then
            puts false
            break
         end
      else
         puts false
         break
      end
      }
      " 2>/dev/null)
      if [ "$provider_path_check" == "false" ] && [ -n "$(pidof clash)" ]; then
         sleep 2
      else
         break
      fi
   done
fi

if [ -z "$(pidof clash)" ] && [ "$provider_path_check" == "false" ]; then
   if [ "$2" = "proxy-providers" ]; then
      LOG_OUT "Error: Failed To Download Proxy-providers, Please Check The Log Page For Detailed error information!"
   else
      LOG_OUT "Error: Failed To Download Rule-providers, Please Check The Log Page For Detailed error information!"
   fi
   LOG_ALERT
   LOG_OUT "Tip: You Can Try to Restart With Meta Core"
   start_fail
fi
}

#获取订阅配置
sub_info_get()
{
   local section="$1" address enabled name
   config_get_bool "enabled" "$section" "enabled" "1"
   config_get "address" "$section" "address" ""
   config_get "name" "$section" "name" ""

   if [ "$subscribe_enable" = "1" ]; then
      return
   fi

   if [ "$enabled" -eq 0 ]; then
      return
   fi

   if [ -z "$address" ]; then
      return
   fi

   if [ -z "$name" ]; then
      SUB_CONFIG_FILE="/etc/openclash/config/config.yaml"
   else
      SUB_CONFIG_FILE="/etc/openclash/config/$name.yaml"
   fi

   if [ "$SUB_CONFIG_FILE" != "$2" ]; then
      return
   fi
   
   subscribe_enable=1
}

#配置文件选择
config_choose()
{
if [ ! -f "$RAW_CONFIG_FILE" ]; then
   config_load "openclash"
   config_foreach sub_info_get "config_subscribe" "$RAW_CONFIG_FILE"
   if [ "$subscribe_enable" = "1" ]; then
      LOG_OUT "【$RAW_CONFIG_FILE】Config File Does Not Exist, You Have Set Subscription Information, Ready To Download..."
      nohup /usr/share/openclash/openclash.sh "$RAW_CONFIG_FILE" &
      del_lock
      exit 0
   fi
fi

if [ -z "$RAW_CONFIG_FILE" ] || [ ! -f "$RAW_CONFIG_FILE" ]; then
   for file_name in /etc/openclash/config/*
   do
      if [ -f "$file_name" ]; then
         CONFIG_NAME=$(echo "$file_name" |awk -F '/' '{print $5}' 2>/dev/null)
         uci -q set openclash.config.config_path="/etc/openclash/config/$CONFIG_NAME"
         uci -q commit openclash
         RAW_CONFIG_FILE="/etc/openclash/config/$CONFIG_NAME"
         CONFIG_FILE="/etc/openclash/$CONFIG_NAME"
         TMP_CONFIG_FILE="/tmp/yaml_config_tmp_$CONFIG_NAME"
         LOG_OUT "Error: Config Not Found, Switch Config File to【$RAW_CONFIG_FILE】"
         break
      fi
   done
fi 2>/dev/null

if [ ! -f "$RAW_CONFIG_FILE" ]; then
   LOG_OUT "Error: Config Not Found"
   del_lock
   exit 0
fi

CONFIG_NAME=$(echo "$RAW_CONFIG_FILE" |awk -F '/' '{print $5}' 2>/dev/null)
HISTORY_PATH_OLD="/etc/openclash/history/${CONFIG_NAME%.*}"
HISTORY_PATH="/etc/openclash/history/${CONFIG_NAME%.*}.db"
}

config_check()
{
#创建启动配置
#rm -rf "/etc/openclash/*.y*" 2>/dev/null
cp "$RAW_CONFIG_FILE" "$TMP_CONFIG_FILE"

ruby -ryaml -rYAML -I "/usr/share/openclash" -E UTF-8 -e "
begin
   YAML.load_file('$RAW_CONFIG_FILE');
rescue Exception => e
   puts '${LOGTIME} Error: Unable To Parse Config File,【' + e.message + '】';
   system 'rm -rf ${TMP_CONFIG_FILE}';
end
" 2>/dev/null >> $LOG_FILE
if [ $? -ne 0 ]; then
   LOG_OUT "Error: Ruby Works Abnormally, Please Check The Ruby Library Depends!"
   start_fail
elif [ ! -f "$TMP_CONFIG_FILE" ] || [ ! -s "$TMP_CONFIG_FILE" ]; then
   LOG_OUT "Error: Config File Format Validation Failed..."
   start_fail
fi
}

yml_other_rules_get()
{
   local section="$1"
   local enabled config
   config_get_bool "enabled" "$section" "enabled" "1"
   config_get "config" "$section" "config" ""

   if [ "$enabled" = "0" ] || [ "$config" != "$2" ]; then
      return
   fi

   if [ -n "$rule_name" ]; then
      return
   fi

   config_get "rule_name" "$section" "rule_name" ""
}

check_run_quick()
{
   quick_start=true
   check_file="$(echo $RAW_CONFIG_FILE | tr " " "?") /etc/openclash/custom/openclash_custom_domain_dns.list /etc/openclash/custom/openclash_custom_domain_dns_policy.list /etc/openclash/custom/openclash_custom_fake_filter.list /etc/openclash/custom/openclash_custom_fallback_filter.yaml /etc/openclash/custom/openclash_custom_hosts.list /etc/openclash/custom/openclash_custom_rules.list /etc/openclash/custom/openclash_custom_rules_2.list $dev_core_path $tun_core_path $meta_core_path $ipdb_path $geosite_path $geoip_path $chnr_path $chnr6_path /usr/share/openclash/res/ConnersHua.yaml /usr/share/openclash/res/ConnersHua_return.yaml /usr/share/openclash/res/lhie1.yaml /etc/openclash/custom/openclash_force_sniffing_domain.yaml /etc/openclash/custom/openclash_sniffing_domain_filter.yaml /etc/openclash/custom/openclash_sniffing_ports_filter.yaml /etc/openclash/custom/openclash_custom_localnetwork_ipv4.list /etc/openclash/custom/openclash_custom_localnetwork_ipv6.list /etc/openclash/custom/openclash_custom_chnroute_pass.list /etc/openclash/custom/openclash_custom_chnroute6_pass.list $cndomain_path /etc/openclash/custom/openclash_custom_overwrite.sh"
	 if [ ! -f "$CONFIG_FILE" ] || [ ! -f "/tmp/openclash_config.tmp" ] || [ ! -f "/tmp/openclash.change" ]; then
	    quick_start=false
	    return
	 fi
	 cmp -s "/etc/config/openclash" "/tmp/openclash_config.tmp"
	 if [ "$?" -ne "0" ]; then
	    LOG_OUT "Tip: Because of the file【 /etc/config/openclash 】modificated, Pause quick start..."
	    quick_start=false
	 else
	    if [ -s "/tmp/openclash.change" ]; then
         for i in $check_file; do
            if [ -z "$(grep "$i $(date -r "$i")$" "/tmp/openclash.change")" ]; then
            	LOG_OUT "Tip: Because of the file【 $i 】modificated, Pause quick start..."
            	quick_start=false
            	break
            fi
         done 2>/dev/null
      fi
	 fi
}

write_run_quick()
{
   cmp -s "/etc/config/openclash" "/tmp/openclash_config.tmp"
	 if [ "$?" -ne "0" ]; then
	    cp "/etc/config/openclash" "/tmp/openclash_config.tmp"
	 fi
	 if ! $quick_start; then
	    : > "/tmp/openclash.change"
	    for i in $check_file; do
         echo "$i $(date -r "$i")" >> "/tmp/openclash.change"
      done 2>/dev/null
	 fi
}

custom_rule_provider()
{
   local section="$1"
   local enabled config
   config_get "config" "$section" "config" ""
   config_get_bool "enabled" "$section" "enabled" "1"

   if [ "$enabled" = "0" ]; then
      return
   fi

   if [ "$config" = "all" ] || [ "$config" = "$CONFIG_NAME" ]; then
      config_set_custom_rule_provider=1
   fi
}

#运行模式处理
do_run_mode()
{
   en_mode=$(uci -q get openclash.config.en_mode)

   if [ "$en_mode" = "fake-ip-tun" ]; then
      en_mode_tun="1"
      en_mode="fake-ip"
   fi

   if [ "$en_mode" = "redir-host-tun" ]; then
      en_mode_tun="1"
      en_mode="redir-host"
   fi

   if [ "$en_mode" = "redir-host-mix" ]; then
      en_mode_tun="2"
      en_mode="redir-host"
   fi

   if [ "$en_mode" = "fake-ip-mix" ]; then
      en_mode_tun="2"
      en_mode="fake-ip"
   fi
}

do_run_file()
{

   #Some MIPS devices file system cound not use db
   source "/etc/openwrt_release"
   [ "$small_flash_memory" == "1" ] || [ -n "$(echo $core_version |grep mips)" ] || [ -n "$(echo $DISTRIB_ARCH |grep mips)" ] || [ -n "$(opkg status libc 2>/dev/null |grep 'Architecture' |awk -F ': ' '{print $2}' |grep mips)" ] && mkdir -p /tmp/etc/openclash && CACHE_PATH="/tmp/etc/openclash/cache.db"

   [ -f "/etc/openclash/geosite.dat" ] && {
      mv "/etc/openclash/geosite.dat" "/etc/openclash/GeoSite.dat" 2>/dev/null
   }

   [ -f "/etc/openclash/geoip.dat" ] && {
      mv "/etc/openclash/geoip.dat" "/etc/openclash/GeoIP.dat" 2>/dev/null
   }

   if [ "$small_flash_memory" != "1" ]; then
      dev_core_path="/etc/openclash/core/clash"
      tun_core_path="/etc/openclash/core/clash_tun"
      meta_core_path="/etc/openclash/core/clash_meta"
      ipdb_path="/etc/openclash/Country.mmdb"
      chnr_path="/etc/openclash/china_ip_route.ipset"
      chnr6_path="/etc/openclash/china_ip6_route.ipset"
      geosite_path="/etc/openclash/GeoSite.dat"
      geoip_path="/etc/openclash/GeoIP.dat"
      cndomain_path="/etc/openclash/accelerated-domains.china.conf"
      mv "/tmp/etc/openclash/Country.mmdb" "$ipdb_path" 2>/dev/null
      mv "/tmp/etc/openclash/china_ip_route.ipset" "$chnr_path" 2>/dev/null
      mv "/tmp/etc/openclash/china_ip6_route.ipset" "$chnr6_path" 2>/dev/null
      mv "/tmp/etc/openclash/GeoSite.dat" "$geosite_path" 2>/dev/null
      mv "/tmp/etc/openclash/GeoIP.dat" "$geoip_path" 2>/dev/null
      mv "/tmp/etc/openclash/accelerated-domains.china.conf" "$cndomain_path" 2>/dev/null
      mv "/tmp/etc/openclash/core/" "/etc/openclash" 2>/dev/null
      if [ "$CACHE_PATH" != "/tmp/etc/openclash/cache.db" ]; then
         rm -rf "/tmp/etc/openclash" 2>/dev/null
      fi
   else
      dev_core_path="/tmp/etc/openclash/core/clash"
      tun_core_path="/tmp/etc/openclash/core/clash_tun"
      meta_core_path="/tmp/etc/openclash/core/clash_meta"
      ipdb_path="/tmp/etc/openclash/Country.mmdb"
      chnr_path="/tmp/etc/openclash/china_ip_route.ipset"
      chnr6_path="/tmp/etc/openclash/china_ip6_route.ipset"
      geosite_path="/tmp/etc/openclash/GeoSite.dat"
      geoip_path="/tmp/etc/openclash/GeoIP.dat"
      cndomain_path="/tmp/etc/openclash/accelerated-domains.china.conf"
      [ ! -h "/etc/openclash/Country.mmdb" ] && mv "/etc/openclash/Country.mmdb" "$ipdb_path" 2>/dev/null
      [ ! -h "/etc/openclash/china_ip_route.ipset" ] && mv "/etc/openclash/china_ip_route.ipset" "$chnr_path" 2>/dev/null
      [ ! -h "/etc/openclash/china_ip6_route.ipset" ] && mv "/etc/openclash/china_ip6_route.ipset" "$chnr6_path" 2>/dev/null
      [ ! -h "/etc/openclash/GeoSite.dat" ] && mv "/etc/openclash/GeoSite.dat" "$geosite_path" 2>/dev/null
      [ ! -h "/etc/openclash/GeoIP.dat" ] && mv "/etc/openclash/GeoIP.dat" "$geoip_path" 2>/dev/null
      [ ! -h "/etc/openclash/accelerated-domains.china.conf" ] && mv "/etc/openclash/accelerated-domains.china.conf" "$cndomain_path" 2>/dev/null
      mv "/etc/openclash/core/" "/tmp/etc/openclash" 2>/dev/null
   fi

   rm -rf "/etc/openclash/cache.db" 2>/dev/null
   rm -rf "/etc/openclash/clash" 2>/dev/null

   if [ "$enable_meta_core" != "1" ]; then
      if [ -n "$en_mode_tun" ]; then
         ln -s "$tun_core_path" /etc/openclash/clash 2>/dev/null
         core_type="TUN"
         core_start_log="Tip: Detected The Exclusive Function of The TUN Core, Use TUN Core to Start..."
      fi

      if [ "$rule_source" != "0" ]; then
         config_load "openclash"
         config_foreach yml_other_rules_get "other_rules" "$CONFIG_NAME"
      fi

      config_load "openclash"
      config_set_custom_rule_provider=0
      for i in "rule_provider_config" "rule_provider_config" "rule_providers" "game_config"; do
         config_foreach custom_rule_provider "$i"
         if [ "$config_set_custom_rule_provider" -eq 1 ]; then
         	break
         fi
      done 2>/dev/null

      if [ "$proxy_mode" = "script" ] || [ "$config_set_custom_rule_provider" -eq 1 ] || [ "$rule_name" = "ConnersHua" ] || [ "$rule_name" = "lhie1" ] || [ -n "$(ruby_read "$RAW_CONFIG_FILE" "['rules'].grep(/(^RULE-SET,|^SCRIPT,)/)")" ] || [ -n "$(ruby_read "/etc/openclash/custom/openclash_custom_rules.list" "['rules'].grep(/(^RULE-SET,|^SCRIPT,)/)")" ] || [ -n "$(ruby_read "/etc/openclash/custom/openclash_custom_rules_2.list" "['rules'].grep(/(^RULE-SET,|^SCRIPT,)/)")" ]; then
         if [ -z "$en_mode_tun" ]; then
            ln -s "$tun_core_path" /etc/openclash/clash 2>/dev/null
            core_type="TUN"
            core_start_log="Tip: Detected The Exclusive Function of The TUN Core, Use TUN Core to Start..."
         fi
      fi
   else
      ln -s "$meta_core_path" /etc/openclash/clash 2>/dev/null
      core_type="Meta"
      core_start_log="Tip: Detected The Exclusive Function of The Meta Core, Use Meta Core to Start..."
   fi

   if [ ! -f "/etc/openclash/clash" ] && [ -f "$dev_core_path" ] && [ -z "$core_type" ]; then
      ln -s "$dev_core_path" /etc/openclash/clash 2>/dev/null
      core_start_log="Tip: No Special Configuration Detected, Use Dev Core to Start..."
   fi

   if [ ! -f "/etc/openclash/clash" ] && [ -f "$tun_core_path" ] && [ -z "$core_type" ]; then
      ln -s "$tun_core_path" /etc/openclash/clash 2>/dev/null
      core_type="TUN"
      core_start_log="Tip: Detected that the Dev Core is not Installed, Use TUN Core to Start..."
   fi

   if [ ! -f "/etc/openclash/clash" ] && [ -f "$meta_core_path" ] && [ -z "$core_type" ]; then
      ln -s "$meta_core_path" /etc/openclash/clash 2>/dev/null
      core_type="Meta"
      core_start_log="Tip: Detected that the Dev Core is not Installed, Use Meta Core to Start..."
   fi

   [ ! -f "$CLASH" ] && {
      LOG_OUT "Tip: Detected that the Core is not Installed, Ready to Download..."
      rm -rf "/tmp/clash_last_version"
      /usr/share/openclash/openclash_core.sh "$core_type"
      if [ "$core_type" == "TUN" ] && [ ! -f "$tun_core_path" ]; then
         start_fail
      elif [ "$core_type" == "Meta" ] && [ ! -f "$meta_core_path" ]; then
         start_fail
      elif [ -z "$core_type" ] && [ ! -f "$dev_core_path" ]; then
         start_fail
      else
         del_lock
         stop
         exit 0
      fi
   }

   [ ! -f "$ipdb_path" ] && {
      LOG_OUT "Tip: Detected that the GEOIP Database is not Installed, Ready to Download..."
      /usr/share/openclash/openclash_ipdb.sh
      if [ ! -f "$ipdb_path" ]; then
         start_fail
      fi
   }

   [ ! -f "$geosite_path" ] && [ "$enable_meta_core" = "1" ] && {
      LOG_OUT "Tip: Detected that the GEOSITE Database is not Installed, Ready to Download..."
      /usr/share/openclash/openclash_geosite.sh
      if [ ! -f "$geosite_path" ]; then
         start_fail
      fi
   }

   [ ! -f "$geoip_path" ] && [ "$enable_geoip_dat" == "1" ] && {
      LOG_OUT "Tip: Detected that the GEOIP Dat is not Installed, Ready to Download..."
      /usr/share/openclash/openclash_geoip.sh
      if [ "$enable_geoip_dat" == "1" ] && [ ! -f "$geoip_path" ]; then
         start_fail
      fi
   }

   if [ "$china_ip_route" = "1" ] || [ "$china_ip6_route" = "1" ] || [ "$disable_udp_quic" = "1" ]; then
      if [ ! -f "$chnr_path" ] || [ ! -f "$chnr6_path" ]; then
         LOG_OUT "Tip: Detected that the Chnroute Cidr or CN Domains List is not Installed, Ready to Download..."
         /usr/share/openclash/openclash_chnroute.sh
      fi
      if [ ! -f "$cndomain_path" ] && [ "$en_mode" = "fake-ip" ] && [ "$china_ip_route" = "1" ]; then
         LOG_OUT "Tip: Detected that the Chnroute Cidr or CN Domains List is not Installed, Ready to Download..."
         /usr/share/openclash/openclash_chnroute.sh
      fi
      if [ -n "$FW4" ]; then
         if [ -z "$(cat "$chnr_path" |grep "define china_ip_route")" ] || [ -z "$(cat "$chnr6_path" |grep "define china_ip6_route")" ]; then
            LOG_OUT "Tip: Detected that the Chnroute Cidr List Format is wrong, Ready to Reformat..."
            /usr/share/openclash/openclash_chnroute.sh
            if [ -z "$(cat "$chnr_path" |grep "define china_ip_route")" ] || [ -z "$(cat "$chnr6_path" |grep "define china_ip6_route")" ]; then
               start_fail
            fi
         fi
      else
         if [ -n "$(cat "$chnr_path" |grep "define china_ip_route")" ] || [ -n "$(cat "$chnr6_path" |grep "define china_ip6_route")" ]; then
            LOG_OUT "Tip: Detected that the Chnroute Cidr List Format is wrong, Ready to Reformat..."
            /usr/share/openclash/openclash_chnroute.sh
            if [ -n "$(cat "$chnr_path" |grep "define china_ip_route")" ] || [ -n "$(cat "$chnr6_path" |grep "define china_ip6_route")" ]; then
               start_fail
            fi
         fi
      fi
      if [ ! -f "$chnr_path" ] || [ ! -f "$chnr6_path" ]; then
         start_fail
      fi
      if [ ! -f "$cndomain_path" ] && [ "$en_mode" = "fake-ip" ] && [ "$china_ip_route" = "1" ]; then
         start_fail
      fi
   fi

   [ ! -x "$tun_core_path" ] && chmod 4755 "$tun_core_path" 2>/dev/null
   [ ! -x "$dev_core_path" ] && chmod 4755 "$dev_core_path" 2>/dev/null
   [ ! -x "$meta_core_path" ] && chmod 4755 "$meta_core_path" 2>/dev/null

   [ -f "$ipdb_path" ] && [ "$small_flash_memory" = "1" ] && {
      ln -s "$ipdb_path" /etc/openclash/Country.mmdb 2>/dev/null
   }

   [ -f "$geosite_path" ] && [ "$small_flash_memory" = "1" ] && {
      ln -s "$geosite_path" /etc/openclash/GeoSite.dat 2>/dev/null
   }

   [ -f "$geoip_path" ] && [ "$small_flash_memory" = "1" ] && {
      ln -s "$geoip_path" /etc/openclash/GeoIP.dat 2>/dev/null
   }

   [ -f "$chnr_path" ] && [ "$small_flash_memory" = "1" ] && {
      ln -s "$chnr_path" /etc/openclash/china_ip_route.ipset 2>/dev/null
   }

   [ -f "$chnr6_path" ] && [ "$small_flash_memory" = "1" ] && {
      ln -s "$chnr6_path" /etc/openclash/china_ip6_route.ipset 2>/dev/null
   }

   [ -f "$cndomain_path" ] && [ "$small_flash_memory" = "1" ] && {
      ln -s "$cndomain_path" /etc/openclash/accelerated-domains.china.conf 2>/dev/null
   }

   #Restore history cache
   if [ -f "$HISTORY_PATH" ] && [ -f "$HISTORY_PATH_OLD" ]; then
      if [ "$(date -r $HISTORY_PATH +%s)" -ge "$(date -r $HISTORY_PATH_OLD +%s)" ]; then
         cmp -s "$CACHE_PATH" "$HISTORY_PATH"
         if [ "$?" -ne "0" ]; then
            if [ "$CACHE_PATH" != "/tmp/etc/openclash/cache.db" ]; then
               ln -s "$HISTORY_PATH" "$CACHE_PATH" 2>/dev/null
            else
               cp "$HISTORY_PATH" "$CACHE_PATH" 2>/dev/null
            fi
         fi
      else
         cmp -s "$CACHE_PATH_OLD" "$HISTORY_PATH_OLD"
         if [ "$?" -ne "0" ]; then
            cp "$HISTORY_PATH_OLD" "$CACHE_PATH_OLD" 2>/dev/null
         fi
      fi
   else
      if [ -f "$HISTORY_PATH" ]; then
         cmp -s "$CACHE_PATH" "$HISTORY_PATH"
         if [ "$?" -ne "0" ]; then
            if [ "$CACHE_PATH" != "/tmp/etc/openclash/cache.db" ]; then
               ln -s "$HISTORY_PATH" "$CACHE_PATH" 2>/dev/null
            else
               cp "$HISTORY_PATH" "$CACHE_PATH" 2>/dev/null
            fi
         fi
      fi
      if [ -f "$HISTORY_PATH_OLD" ]; then
         cmp -s "$CACHE_PATH_OLD" "$HISTORY_PATH_OLD"
         if [ "$?" -ne "0" ]; then
            cp "$HISTORY_PATH_OLD" "$CACHE_PATH_OLD" 2>/dev/null
         fi
      fi
   fi

   if [ "$CACHE_PATH" == "/tmp/etc/openclash/cache.db" ]; then
      [ ! -f "$CACHE_PATH" ] && touch "$CACHE_PATH"
      ln -s "$CACHE_PATH" /etc/openclash/cache.db 2>/dev/null
   else
      [ ! -f "$CACHE_PATH" ] && touch "$HISTORY_PATH"
      ln -s "$HISTORY_PATH" "$CACHE_PATH" 2>/dev/null
   fi

   if ! capsh --is-uid=0 >/dev/null || ! capsh --has-ambient >/dev/null; then
      LOG_OUT "Error: Could Not Load The Capsh Library, Please Verify The Capsh Shell Library Work Well..."
      LOG_OUT "Tip: You Could Download And Re-Install The libcap & libcap-bin Library From The Address Give"
      echo "" >> $LOG_FILE
      echo "---------- https://mirrors.cloud.tencent.com/lede/snapshots/packages/ ----------" >> $LOG_FILE
      echo "" >> $LOG_FILE
      start_fail
   fi


   #创建原始备份
   if [ ! -f "$2" ]; then
      cp "$1" "$2"
   fi

   #保存启动内核类型
   uci -q set openclash.config.core_type="$core_type"
   uci -q commit openclash

}

config_test()
{
   if [ -f "$CLASH" ]; then
      LOG_OUT "Test The Config File First..."
      test_info=$(nohup $CLASH -t -d $CLASH_CONFIG -f "$CONFIG_FILE")
      local IFS=$'\n'
      for i in $test_info; do
         if [ -n "$(echo "$i" |grep "configuration file")" ]; then
            local info=$(echo "$i" |sed "s# ${CONFIG_FILE} #【${CONFIG_FILE}】#g")
            LOG_OUT "$info"
         else
            echo "$i" >> "$LOG_FILE"
         fi
      done
      if [ -n "$(echo "$test_info" |grep "test failed")" ]; then
         return 1
      fi
   else
      return 0
   fi
}

start_run_core()
{
   LOG_OUT "$core_start_log"
   ulimit -SHn 65535 2>/dev/null
   ulimit -v unlimited 2>/dev/null
   modprobe tun >/dev/null 2>&1
   if ! $quick_start; then
      mv "$TMP_CONFIG_FILE" "$CONFIG_FILE" 2>/dev/null
      rm -rf "$TMP_CONFIG_FILE" 2>/dev/null
   fi
   config_test
   if [ $? -ne 0 ]; then
      LOG_OUT "Error: Config File Tested Faild, Please Check The Log Infos!"
      start_fail
   fi
   config_reload=$(uci -q get openclash.config.config_reload)
   if [ -n "$(pidof clash)" ] && [ "$core_type" != "TUN" ] && [ "$core_type" != "Meta" ] && [ "$config_reload" != "0" ]; then
      reload_status=$(curl -s --connect-timeout 5 -m 5 -o /dev/null -w %{http_code} -H 'Content-Type: application/json' -H "Authorization: Bearer ${da_password}" -XPUT http://"$lan_ip":"$cn_port"/configs?force=true -d "{\"path\": \"$CONFIG_FILE\"}" 2>/dev/null)
   fi
   if [ "$reload_status" != "204" ] || [ -z "$(pidof clash)" ] || [ "$core_type" = "TUN" ] || [ "$core_type" = "Meta" ] || [ "$config_reload" = "0" ]; then
      kill_clash
      #防止赋权失败
      touch "/tmp/openclash.log" 2>/dev/null
      chmod o+w /etc/openclash/proxy_provider/* 2>/dev/null
      chmod o+w /etc/openclash/rule_provider/* 2>/dev/null
      chmod o+w /etc/openclash/history/* 2>/dev/null
      chmod o+w /etc/openclash/cache.db 2>/dev/null
      chmod o+w /tmp/openclash.log 2>/dev/null
      chown nobody:nogroup /etc/openclash/core/* 2>/dev/null
      #使用nobody启动内核方便代理路由自身流量
      capabilties="cap_sys_resource,cap_dac_override,cap_net_raw,cap_net_bind_service,cap_net_admin,cap_sys_ptrace"
      capsh --caps="${capabilties}+eip" -- -c "capsh --user=nobody --addamb='${capabilties}' -- -c 'nohup $CLASH -d $CLASH_CONFIG -f \"$CONFIG_FILE\" >> $LOG_FILE 2>&1 &'" >> $LOG_FILE 2>&1
   fi
   uci -q set openclash.config.config_reload=1
   uci -q commit openclash
}

check_core_status()
{
   check_time=1
   while ( [ "$check_time" -le 3 ] && [ -n "$(pidof clash)" ] )
   do
      sleep 1
      let check_time++
   done
   if [ -z "$(pidof clash)" ]; then
      LOG_ALERT
   fi
}

#不修改配置文件启动
raw_config_start()
{
   cp "$RAW_CONFIG_FILE" "$CONFIG_FILE"
   dns_port=$(ruby_read "$CONFIG_FILE" "['dns']['listen'].split(':')[1]")
   en_mode=$(ruby_read "$CONFIG_FILE" "['dns']['enhanced-mode']")
   proxy_port=$(ruby_read "$CONFIG_FILE" "['redir-port']")

   if [ -z "$dns_port" ] || [ -z "$en_mode" ] || [ -z "$proxy_port" ]; then
      if [ -z "$dns_port" ]; then
         LOG_OUT "Error: Get DNS 'listen' Option Error, OpenClash Can Not Start With Raw Config File"
      fi
      if [ -z "$en_mode" ]; then
         LOG_OUT "Error: Get DNS 'enhanced-mode' Option Error, OpenClash Can Not Start With Raw Config File"
      fi
      if [ -z "$proxy_port" ]; then
         LOG_OUT "Error: Get General 'redir-port' Option Error, OpenClash Can Not Start With Raw Config File"
      fi
      start_fail
   fi

   start_run_core
   check_core_status

   if ! pidof clash >/dev/null; then
      LOG_OUT "Error: OpenClash Can Not Start, Please Check The Error Info And Try Again!"
      start_fail
   fi

   if [ "$en_mode" = "redir-host" ]; then
      case $en_mode_tun in
      "1")
         uci -q set openclash.config.en_mode=redir-host-tun
      ;;
      "2")
         uci -q set openclash.config.en_mode=redir-host-mix
      ;;
      *)
         uci -q set openclash.config.en_mode=redir-host
      esac
   elif [ "$en_mode" = "fake-ip" ]; then
   	case $en_mode_tun in
      "1")
         uci -q set openclash.config.en_mode=fake-ip-tun
      ;;
      "2")
         uci -q set openclash.config.en_mode=fake-ip-mix
      ;;
      *)
         uci -q set openclash.config.en_mode=fake-ip
      esac
   fi

   dase=$(ruby_read "$CONFIG_FILE" "['secret']")
   uci -q set openclash.config.dashboard_password="$dase"

   cn_port=$(ruby_read "$CONFIG_FILE" "['external-controller'].split(':')[1]")
   uci -q set openclash.config.cn_port="$cn_port"

   uci -q set openclash.config.proxy_port="$proxy_port"
   uci -q set openclash.config.restricted_mode=1

   uci commit openclash
}

try_restore_start()
{
   if [ -z "$(pidof clash)" ]; then
      if [ "$rule_source" = 0 ] && [ "$enable_custom_clash_rules" = 0 ]; then
         LOG_OUT "Error: OpenClash Can Not Start, Try Use Raw Config Restart Again..."
         raw_config_start
      else
         LOG_OUT "Error: OpenClash Can Not Start, Try Use Backup Rules Start Again..."
         ruby -ryaml -rYAML -I "/usr/share/openclash" -E UTF-8 -e "
         begin
            Value = YAML.load_file('$RAW_CONFIG_FILE');
            Value_1 = YAML.load_file('$CONFIG_FILE');
            if Value.has_key?('rule-providers') then
               Value_1['rule-providers'] = Value.select {|x| 'rule-providers' == x}['rule-providers'];
            end;
            if Value.has_key?('script') then
               Value_1['script'] = Value.select {|x| 'script' == x}['script'];
            end;
            if Value.has_key?('rules') then
               Value_1['rules'] = Value.select {|x| 'rules' == x}['rules'];
            end;
            File.open('$CONFIG_FILE','w') {|f| YAML.dump(Value_1, f)};
         rescue Exception => e
            puts '${LOGTIME} Error: Restore Backup Rules Failed,【' + e.message + '】';
         end
         " 2>/dev/null >> $LOG_FILE
         start_run_core
         check_core_status
         if ! pidof clash >/dev/null; then
            LOG_OUT "Error: OpenClash Can Not Start, Try Use Raw Config Restart Again..."
            raw_config_start
         fi
      fi
   fi
}

#防火墙设置部分
nft_ac_add()
{
   if [ -z "$1" ]; then
      return
   fi

   nft add element inet fw4 "$2" { "$1" } 2>/dev/null
   [ -n "$3" ] && nft add element inet fw4 "$3" { "$1" } 2>/dev/null
}

ac_add()
{
   if [ -z "$1" ]; then
      return
   fi

   ipset add "$2" "$1" 2>/dev/null
   [ -n "$3" ] && ipset add "$3" "$1" 2>/dev/null
}

upnp_exclude()
{
   if [ -s "$upnp_lease_file" ]; then
      cat "$upnp_lease_file" |while read -r line
      do
         if [ -n "$line" ]; then
            upnp_ip=$(echo "$line" |awk -F ':' '{print $3}')
            upnp_dp=$(echo "$line" |awk -F ':' '{print $4}')
            upnp_type=$(echo "$line" |awk -F ':' '{print $1}')
            if [ -n "$upnp_ip" ] && [ -n "$upnp_dp" ]; then
               if [ -n "$FW4" ]; then
                  if [ -z "$(nft list chain inet fw4 openclash_upnp |grep "$upnp_ip" |grep "$upnp_dp")" ]; then
                     if [ "$upnp_type" == "UDP" ]; then
                        nft add rule inet fw4 openclash_upnp ip saddr { "$upnp_ip" } udp sport "$upnp_dp" counter return 2>/dev/null
                     else
                        nft add rule inet fw4 openclash_upnp ip saddr { "$upnp_ip" } tcp sport "$upnp_dp" counter return 2>/dev/null
                     fi
                  fi
               else
                  if [ -z "$(iptables -t mangle -nL openclash_upnp |grep "$upnp_ip" |grep "$upnp_dp")" ]; then
                     if [ "$upnp_type" == "UDP" ]; then
                        iptables -t mangle -A openclash_upnp -p udp -s "$upnp_ip" --sport "$upnp_dp" -j RETURN 2>/dev/null
                     else
                        iptables -t mangle -A openclash_upnp -p tcp -s "$upnp_ip" --sport "$upnp_dp" -j RETURN 2>/dev/null
                     fi
                  fi
               fi
            fi
         fi
      done >/dev/null 2>&1
   fi
}

firewall_rule_exclude()
{
   local section="$1"
   local name src dest dest_port proto target enabled family

   config_get "name" "$section" "name" ""
   config_get "src" "$section" "src" ""
   config_get "dest" "$section" "dest" ""
   config_get "dest_port" "$section" "dest_port" ""
   config_get "dest_ip" "$section" "dest_ip" ""
   config_get "proto" "$section" "proto" ""
   config_get "target" "$section" "target" ""
   config_get "enabled" "$section" "enabled" ""
   config_get "family" "$section" "family" ""

   if [ a"$target" != aACCEPT  ] || [ a"$enabled" == a0 ]; then
      return
   fi

   local e_udp=false
   local e_tcp=false
   for p in $proto; do
       if [ $p == tcp ]; then e_tcp=true; fi
       if [ $p == udp ]; then e_udp=true; fi
       if [ $p == all ]; then e_tcp=true; e_udp=true; fi
   done

   if [ -z "$proto" ]; then e_tcp=true; e_udp=true; fi

   if ! $e_udp && ! $e_tcp ; then
       return
   fi

   if [ -n "$(echo $dest_port |grep -E '\-|\:'  2>/dev/null)" ]; then
      LOG_OUT "Warning: Because there is a port range【$dest_port】in the firewall rule settings【$name】auto bypassing may cause the normal connection of the client not to reach the core, if necessary, please add your own in the access control!"
      return
   fi

   if [ -n "$FW4" ]; then
      if [ -z "$family" ] || [ "$family" == "ipv4" ]; then
         if [ -z "$en_mode_tun" ] || [ "$en_mode_tun" -eq 2 ]; then
            for i in $dest_port; do
               if $e_tcp ; then
                  nft insert rule inet fw4 openclash_output position 0 meta nfproto {ipv4} tcp sport "$i" counter return >/dev/null 2>&1
                  if [ -z "$dest_ip" ]; then
                     nft insert rule inet fw4 openclash position 0 meta nfproto {ipv4} tcp sport "$i" counter return >/dev/null 2>&1
                  else
                     nft insert rule inet fw4 openclash position 0 ip saddr { "$dest_ip" } tcp sport "$i" counter return >/dev/null 2>&1
                  fi
               fi
               if $e_udp ; then
                  nft insert rule inet fw4 openclash_mangle_output position 0 meta nfproto {ipv4} udp sport "$i" counter return >/dev/null 2>&1
                  if [ -z "$dest_ip" ]; then
                     nft insert rule inet fw4 openclash_mangle position 0 meta nfproto {ipv4} udp sport "$i" counter return >/dev/null 2>&1
                  else
                     nft insert rule inet fw4 openclash_mangle position 0 ip saddr { "$dest_ip" } udp sport "$i" counter return >/dev/null 2>&1
                  fi
               fi
            done
         elif [ "$en_mode_tun" -eq 1 ]; then
            for i in $dest_port; do
               if $e_tcp ; then
                  nft insert rule inet fw4 openclash_mangle_output position 0 meta nfproto {ipv4} tcp sport "$i" counter return >/dev/null 2>&1
                  if [ -z "$dest_ip" ]; then
                     nft insert rule inet fw4 openclash_mangle position 0 meta nfproto {ipv4} tcp sport "$i" counter return >/dev/null 2>&1
                  else
                     nft insert rule inet fw4 openclash_mangle position 0 ip saddr { "$dest_ip" } tcp sport "$i" counter return >/dev/null 2>&1
                  fi
               fi
               if $e_udp ; then
                  nft insert rule inet fw4 openclash_mangle_output position 0 meta nfproto {ipv4} udp sport "$i" counter return >/dev/null 2>&1
                  if [ -z "$dest_ip" ]; then
                     nft insert rule inet fw4 openclash_mangle position 0 meta nfproto {ipv4} udp sport "$i" counter return >/dev/null 2>&1
                  else
                     nft insert rule inet fw4 openclash_mangle position 0 ip saddr { "$dest_ip" } udp sport "$i" counter return >/dev/null 2>&1
                  fi
               fi
            done
         fi
      fi

      if [ "$ipv6_enable" -eq 1 ]; then
         if [ -z "$family" ] || [ "$family" == "ipv6" ]; then
            for i in $dest_port; do
               if $e_tcp ; then
                  if [ -z "$dest_ip" ]; then
                     nft insert rule inet fw4 openclash_mangle_v6 position 0 meta nfproto {ipv6} tcp sport "$i" counter return >/dev/null 2>&1
                  else
                     nft insert rule inet fw4 openclash_mangle_v6 position 0 ip6 saddr { "$dest_ip" } tcp sport "$i" counter return >/dev/null 2>&1
                  fi
                  nft insert rule inet fw4 openclash_mangle_output_v6 position 0 meta nfproto {ipv6} tcp sport "$i" counter return >/dev/null 2>&1
               fi
               if $e_udp ; then
                  if [ -z "$dest_ip" ]; then
                     nft insert rule inet fw4 openclash_mangle_v6 position 0 meta nfproto {ipv6} udp sport "$i" counter return >/dev/null 2>&1
                  else
                     nft insert rule inet fw4 openclash_mangle_v6 position 0 ip6 saddr { "$dest_ip" } udp sport "$i" counter return >/dev/null 2>&1
                  fi
                  nft insert rule inet fw4 openclash_mangle_output_v6 position 0 meta nfproto {ipv6} udp sport "$i" counter return >/dev/null 2>&1
               fi
            done
         fi
      fi
   else
      dest_port=$(echo $dest_port |sed "s/-/:/g" 2>/dev/null)
      dest_ip=$(echo $dest_ip |sed "s/ /,/g" 2>/dev/null)

      if [ -z "$family" ] || [ "$family" == "ipv4" ]; then
         if [ -z "$en_mode_tun" ] || [ "$en_mode_tun" -eq 2 ]; then
            for i in $dest_port; do
               if $e_tcp ; then
                  iptables -t nat -I openclash_output -p tcp --sport "$i" -j RETURN >/dev/null 2>&1
                  if [ -z "$dest_ip" ]; then
                     iptables -t nat -I openclash -p tcp --sport "$i" -j RETURN >/dev/null 2>&1
                  else
                     iptables -t nat -I openclash -p tcp -s "$dest_ip" --sport "$i" -j RETURN >/dev/null 2>&1
                  fi
               fi
               if $e_udp ; then
                  iptables -t mangle -I openclash_output -p udp --sport "$i" -j RETURN >/dev/null 2>&1
                  if [ -z "$dest_ip" ]; then
                     iptables -t mangle -I openclash -p udp --sport "$i" -j RETURN >/dev/null 2>&1
                  else
                     iptables -t mangle -I openclash -p udp -s "$dest_ip" --sport "$i" -j RETURN >/dev/null 2>&1
                  fi
               fi
            done
         elif [ "$en_mode_tun" -eq 1 ]; then
            for i in $dest_port; do
               if $e_tcp ; then
                  iptables -t mangle -I openclash_output -p tcp --sport "$i" -j RETURN >/dev/null 2>&1
                  if [ -z "$dest_ip" ]; then
                     iptables -t mangle -I openclash -p tcp --sport "$i" -j RETURN >/dev/null 2>&1
                  else
                     iptables -t mangle -I openclash -p tcp -s "$dest_ip" --sport "$i" -j RETURN >/dev/null 2>&1
                  fi
               fi
               if $e_udp ; then
                  iptables -t mangle -I openclash_output -p udp --sport "$i" -j RETURN >/dev/null 2>&1
                  if [ -z "$dest_ip" ]; then
                     iptables -t mangle -I openclash -p udp --sport "$i" -j RETURN >/dev/null 2>&1
                  else
                     iptables -t mangle -I openclash -p udp -s "$dest_ip" --sport "$i" -j RETURN >/dev/null 2>&1
                  fi
               fi
            done
         fi
      fi

      if [ "$ipv6_enable" -eq 1 ] && [ -n "$(ip6tables -t mangle -L 2>&1 | grep -o 'Chain')" ]; then
         if [ -z "$family" ] || [ "$family" == "ipv6" ]; then
            for i in $dest_port; do
               if $e_tcp ; then
                  if [ -z "$dest_ip" ]; then
                     ip6tables -t mangle -I openclash -p tcp --sport "$i" -j RETURN >/dev/null 2>&1
                  else
                     ip6tables -t mangle -I openclash -s "$dest_ip" -p tcp --sport "$i" -j RETURN >/dev/null 2>&1
                  fi
                  ip6tables -t mangle -I openclash_output -p tcp --sport "$i" -j RETURN >/dev/null 2>&1
               fi
               if $e_udp ; then
                  if [ -z "$dest_ip" ]; then
                     ip6tables -t mangle -I openclash -p udp --sport "$i" -j RETURN >/dev/null 2>&1
                  else
                     ip6tables -t mangle -I openclash -s "$dest_ip" -p udp --sport "$i" -j RETURN >/dev/null 2>&1
                  fi
                  ip6tables -t mangle -I openclash_output -p udp --sport "$i" -j RETURN >/dev/null 2>&1
               fi
            done
         fi
      fi
   fi
}

firewall_redirect_exclude()
{
   local section="$1"
   local name src_dport dest_port dest_ip proto enabled
   config_get "name" "$section" "name" ""
   config_get "src_dport" "$section" "src_dport" ""
   config_get "dest_port" "$section" "dest_port" ""
   config_get "dest_ip" "$section" "dest_ip" ""
   config_get "proto" "$section" "proto" ""
   config_get "enabled" "$section" "enabled" ""

   if [ -z "$src_dport" ] || [ a"$enabled" == a0 ]; then
      return
   fi

   if [ -n "$(echo $dest_port |grep -E '\-|\:'  2>/dev/null)" ]; then
      LOG_OUT "Warning: Because there is a port range【$dest_port】in the firewall rule settings【$name】auto bypassing may cause the normal connection of the client not to reach the core, if necessary, please add your own in the access control!"
      return
   fi

   local e_udp=false
   local e_tcp=false
   for p in $proto; do
       if [ $p == tcp ]; then e_tcp=true; fi
       if [ $p == udp ]; then e_udp=true; fi
       if [ $p == all ]; then e_tcp=true; e_udp=true; fi
   done

   if [ -z "$proto" ]; then e_tcp=true; e_udp=true; fi

   if ! $e_udp && ! $e_tcp ; then
       return
   fi

   if [ -n "$FW4" ]; then
      if [ -z "$en_mode_tun" ] || [ "$en_mode_tun" -eq 2 ]; then
         if $e_tcp ; then
            nft insert rule inet fw4 openclash_output position 0 ip saddr { "$dest_ip" } tcp sport "$dest_port" counter return >/dev/null 2>&1
         fi
         if $e_udp ; then
            nft insert rule inet fw4 openclash_mangle_output position 0 ip saddr { "$dest_ip" } udp sport "$dest_port" counter return >/dev/null 2>&1
            if [ -n "$dest_ip" ]; then
               nft insert rule inet fw4 openclash_mangle position 0 ip saddr { "$dest_ip" } udp sport "$dest_port" counter return >/dev/null 2>&1
            fi
         fi
      elif [ "$en_mode_tun" -eq 1 ]; then
         if $e_tcp ; then
            nft insert rule inet fw4 openclash_mangle_output position 0 ip saddr { "$dest_ip" } tcp sport "$dest_port" counter return >/dev/null 2>&1
            if [ -n "$dest_ip" ]; then
               nft insert rule inet fw4 openclash_mangle position 0  ip saddr { "$dest_ip" } tcp sport "$dest_port" counter return >/dev/null 2>&1
            fi
         fi
         if $e_udp ; then
            nft insert rule inet fw4 openclash_mangle_output position 0 ip saddr { "$dest_ip" } udp sport "$dest_port" counter return >/dev/null 2>&1
            if [ -n "$dest_ip" ]; then
               nft insert rule inet fw4 openclash_mangle position 0 ip saddr { "$dest_ip" } udp sport "$dest_port" counter return >/dev/null 2>&1
            fi
         fi
      fi

      if [ "$ipv6_enable" -eq 1 ]; then
         if $e_tcp ; then
            if [ -n "$dest_ip" ]; then
               nft insert rule inet fw4 openclash_mangle_v6 position 0 ip6 saddr { "$dest_ip" } tcp sport "$dest_port" counter return >/dev/null 2>&1
            fi
            nft insert rule inet fw4 openclash_mangle_output_v6 position 0 ip6 saddr { "$dest_ip" } tcp sport "$dest_port" counter return >/dev/null 2>&1
         fi
         if $e_udp ; then
            if [ -n "$dest_ip" ]; then
               nft insert rule inet fw4 openclash_mangle_v6 position 0 ip6 saddr { "$dest_ip" } udp sport "$dest_port" counter return >/dev/null 2>&1
            fi
            nft insert rule inet fw4 openclash_mangle_output_v6 position 0 ip6 saddr { "$dest_ip" } udp sport "$dest_port" counter return >/dev/null 2>&1
         fi
      fi
   else
      dest_port=$(echo $dest_port |sed "s/-/:/g" 2>/dev/null)
      dest_ip=$(echo $dest_ip |sed "s/ /,/g" 2>/dev/null)
      [ -n "$dest_ip" ] && dest_ip="-s ${dest_ip}"

      if [ -z "$en_mode_tun" ] || [ "$en_mode_tun" -eq 2 ]; then
         if $e_tcp ; then
            iptables -t nat -I openclash_output "$dest_ip" -p tcp --sport "$dest_port" -j RETURN >/dev/null 2>&1
         fi
         if $e_udp ; then
            iptables -t mangle -I openclash_output "$dest_ip" -p udp --sport "$dest_port" -j RETURN >/dev/null 2>&1
            if [ -n "$dest_ip" ]; then
               iptables -t mangle -I openclash "$dest_ip" -p udp --sport "$dest_port" -j RETURN >/dev/null 2>&1
            fi
         fi
      elif [ "$en_mode_tun" -eq 1 ]; then
         if $e_tcp ; then
            iptables -t mangle -I openclash_output -p tcp "$dest_ip" --sport "$dest_port" -j RETURN >/dev/null 2>&1
            if [ -n "$dest_ip" ]; then
               iptables -t mangle -I openclash -p tcp "$dest_ip" --sport "$dest_port" -j RETURN >/dev/null 2>&1
            fi
         fi
         if $e_udp ; then
            iptables -t mangle -I openclash_output -p udp "$dest_ip" --sport "$dest_port" -j RETURN >/dev/null 2>&1
            if [ -n "$dest_ip" ]; then
               iptables -t mangle -I openclash -p udp "$dest_ip" --sport "$dest_port" -j RETURN >/dev/null 2>&1
            fi
         fi
      fi

      if [ "$ipv6_enable" -eq 1 ] && [ -n "$(ip6tables -t mangle -L 2>&1 | grep -o 'Chain')" ]; then
         if $e_tcp ; then
            if [ -n "$dest_ip" ]; then
               ip6tables -t mangle -I openclash -p tcp "$dest_ip" --sport "$dest_port" -j RETURN >/dev/null 2>&1
            fi
            ip6tables -t mangle -I openclash_output -p tcp "$dest_ip" --sport "$dest_port" -j RETURN >/dev/null 2>&1
         fi
         if $e_udp ; then
            if [ -n "$dest_ip" ]; then
               ip6tables -t mangle -I openclash -p udp "$dest_ip" --sport "$dest_port" -j RETURN >/dev/null 2>&1
            fi
            ip6tables -t mangle -I openclash_output -p udp "$dest_ip" --sport "$dest_port" -j RETURN >/dev/null 2>&1
         fi
      fi
   fi
}

set_tun_tap()
{
      #启动TUN
      if [ -z "$1" ]; then
         ip_="ip"
      else
         ip_="ip -6"
      fi

      TUN_WAIT=0
      TUN_RESTART=1

      if [ -n "$(pidof clash)" ] && [ -n "$1" ] && [ "$(ip -6 route list |grep utun |wc -l)" -ne 2 ] && [ -n "$(ifconfig utun)" ]; then
         if [ "$enable_meta_core" = "1" ]; then
            ip -6 addr add fdfe:dcba:9876::1/126 dev utun >/dev/null 2>&1
            ip -6 route add fdfe:dcba:9876::/126 dev utun proto kernel metric 256 pref medium >/dev/null 2>&1
            ip -6 route add fe80::/64 dev utun proto kernel metric 256 pref medium >/dev/null 2>&1
         fi
         ip -6 route replace default dev utun table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1
         ip -6 rule add fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1
      fi

      #prevent lost when v6 utun address added
      if [ -n "$(pidof clash)" ] && [ -z "$(ip route list |grep utun)" ] && [ -n "$(ifconfig utun)" ]; then
         route add -net "$fakeip_range" dev utun >/dev/null 2>&1
         ip route replace default dev utun table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1
         ip rule add fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1
      fi

      $ip_ link set utun up

      LOG_OUT "Tip: Waiting for TUN Interface Start..."
      while ( [ -n "$(pidof clash)" ] && [ -z "$($ip_ route list |grep utun)" ] && [ "$TUN_WAIT" -le 30 ] )
      do
         $ip_ link set utun up
         let TUN_WAIT++
         sleep 2
      done

      if [ -n "$(pidof clash)" ] && [ -z "$($ip_ route list |grep utun)" ] && [ "$TUN_WAIT" -gt 10 ]; then
         while ( [ -n "$(pidof clash)" ] && [ -z "$($ip_ route list |grep utun)" ] && [ "$TUN_RESTART" -le 3 ] )
         do
            LOG_OUT "Warning: TUN Interface Start Failed, Try to Restart Again..."
            kill_clash
            sleep 3
            start_run_core
            check_core_status
            sleep 10
            let TUN_RESTART++
         done
         if [ -n "$(pidof clash)" ] && [ -z "$($ip_ route list |grep utun)" ] && [ "$TUN_RESTART" -gt 3 ]; then
            LOG_OUT "Warning: TUN Interface Start Failed, Please Check The Dependence or Try to Restart Again!"
            start_fail
         fi
      fi

      if [ -n "$1" ] && [ "$enable_meta_core" = "1" ]; then
         ip -6 rule del oif utun table 2022 >/dev/null 2>&1
         ip -6 route del default dev utun table 2022 >/dev/null 2>&1
      fi
      $ip_ route replace default dev utun table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1
      $ip_ rule add fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1
}

set_firewall()
{

if [ -z "$(uci -q get firewall.openclash)" ] || [ -z "$(uci -q get ucitrack.@openclash[-1].init)" ]; then
   uci -q delete ucitrack.@openclash[-1]
   uci -q add ucitrack openclash
   uci -q set ucitrack.@openclash[-1].init=openclash
   uci -q commit ucitrack
   uci -q delete firewall.openclash
   uci -q set firewall.openclash=include
   uci -q set firewall.openclash.type=script
   uci -q set firewall.openclash.path=/var/etc/openclash.include
   [ -n "$FW4" ] || uci -q set firewall.openclash.reload=1
   uci -q commit firewall
fi

mkdir -p /var/etc
cat > "/var/etc/openclash.include" <<-EOF
/etc/init.d/openclash reload "firewall" >/dev/null 2>&1
EOF

#common ports
if [ -n "$common_ports" ] && [ "$common_ports" != "0" ]; then
   if [ "$common_ports" = "1" ]; then
      common_port="21 22 23 53 80 123 143 194 443 465 587 853 993 995 998 2052 2053 2082 2083 2086 2095 2096 5222 5228 5229 5230 8080 8443 8880 8888 8889"
   else
      common_port=$common_ports
   fi
fi

local settype nftflag
if dnsmasq --version | grep -q 'Compile time options:.* nftset'; then
   settype="nftset"
   nftflag="inet#fw4#"
else
   settype="ipset"
   [ -n "$FW4" ] && LOG_OUT "Warning: Dnsmasq not Support nftset, Use ipset..."
fi

case $enable_redirect_dns in
	"1")
   LOG_OUT "Tip: DNS Hijacking Mode is Dnsmasq Redirect..."
   ;;
   "2")
   LOG_OUT "Tip: DNS Hijacking Mode is Firewall Redirect..."
   ;;
   *)
   LOG_OUT "Tip: DNS Hijacking is Disabled..."
esac

if [ "$ipv6_mode" -eq 2 ] && [ "$enable_meta_core" -ne 1 ]; then
   LOG_OUT "Warning: Only Meta Core Support IPv6 Tun Mode, Use TProxy Instead..."
   ipv6_mode=0
fi

if [ "$ipv6_enable" -eq 1 ]; then
   case $ipv6_mode in
      "1")
      LOG_OUT "Tip: IPv6 Proxy Mode is Redirect..."
      ;;
      "2")
      LOG_OUT "Tip: IPv6 Proxy Mode is TUN..."
      ;;
      *)
      LOG_OUT "Tip: IPv6 Proxy Mode is TProxy..."
   esac
fi

#NFTABLES
if [ -n "$FW4" ]; then
   LOG_OUT "Tip: Firewall4 was Detected, Use NFTABLE Rules..."
   if [ "$china_ip_route" = "1" ] || [ "$disable_udp_quic" = "1" ]; then
      nft 'flush set inet fw4 china_ip_route'
      nft -f '/etc/openclash/china_ip_route.ipset'
      CHNROUTE_WAIT=0
      while ( [ -z "$(nft list sets |grep "set china_ip_route {")" ] && [ "$CHNROUTE_WAIT" -le 3 ] )
      do
         nft -f '/etc/openclash/china_ip_route.ipset'
      done

      if [ "$enable_redirect_dns" != "2" ]; then
         mkdir -p ${DNSMASQ_CONF_DIR}
         echo "add set inet fw4 china_ip_route_pass { type ipv4_addr; flags interval; auto-merge; }" >>/tmp/openclash_china_ip_route_pass.list
         [ -z `(awk '!/^$/&&!/^#/&&/(^([1-9]|1[0-9]|1[1-9]{2}|2[0-4][0-9]|25[0-5])\.)(([0-9]{1,2}|1[1-9]{2}|2[0-4][0-9]|25[0-5])\.){2}([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-5][0-9]|25[0-4])((\/[0-9][0-9])?)$/{printf("    %s,'" "'\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute_pass.list)` ] || {
            echo "define china_ip_route_pass = {" >/tmp/openclash_china_ip_route_pass.list
            awk '!/^$/&&!/^#/&&/(^([1-9]|1[0-9]|1[1-9]{2}|2[0-4][0-9]|25[0-5])\.)(([0-9]{1,2}|1[1-9]{2}|2[0-4][0-9]|25[0-5])\.){2}([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-5][0-9]|25[0-4])((\/[0-9][0-9])?)$/{printf("    %s,'" "'\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute_pass.list >>/tmp/openclash_china_ip_route_pass.list 2>/dev/null
            echo "}" >>/tmp/openclash_china_ip_route_pass.list
            echo 'add element inet fw4 china_ip_route_pass $china_ip_route_pass' >>/tmp/openclash_china_ip_route_pass.list
         }
         awk '!/^$/&&!/^#/&&!/(^([1-9]|1[0-9]|1[1-9]{2}|2[0-4][0-9]|25[0-5])\.)(([0-9]{1,2}|1[1-9]{2}|2[0-4][0-9]|25[0-5])\.){2}([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-5][0-9]|25[0-4])((\/[0-9][0-9])?)$/{printf("'${settype}'=/%s/'${nftflag}'china_ip_route_pass'" "'\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute_pass.list >>${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute_pass.conf 2>/dev/null
         nft 'flush set inet fw4 china_ip_route_pass'
         nft -f '/tmp/openclash_china_ip_route_pass.list'
         rm -rf /tmp/openclash_china_ip_route_pass.list

         if [ "$en_mode" = "fake-ip" ] && [ "$china_ip_route" = "1" ]; then
            cat "/etc/openclash/accelerated-domains.china.conf" |awk -v dns="${custom_china_domain_dns_server}" -F '/' '!/^$/&&!/^#/{print $1"/"$2"/"dns}' >${DNSMASQ_CONF_DIR}/dnsmasq_accelerated-domains.china.conf 2>/dev/null
            for i in `awk '!/^$/&&!/^#/&&!/(^([1-9]|1[0-9]|1[1-9]{2}|2[0-4][0-9]|25[0-5])\.)(([0-9]{1,2}|1[1-9]{2}|2[0-4][0-9]|25[0-5])\.){2}([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-5][0-9]|25[0-4])((\/[0-9][0-9])?)$/{printf("%s\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute_pass.list`
            do
               sed -i "/server=\/${i}\//d" ${DNSMASQ_CONF_DIR}/dnsmasq_accelerated-domains.china.conf
            done
         fi
      fi
   fi

   #lan_google_dns_ac
   if [ -n "$(uci -q get openclash.config.lan_block_google_dns_ips)" ]; then
      nft 'add set inet fw4 lan_block_google_dns_ips { type ipv4_addr; flags interval; auto-merge; }'
      nft 'add set inet fw4 lan_block_google_dns_ipv6s { type ipv6_addr; flags interval; auto-merge; }'
      config_load "openclash"
      config_list_foreach "config" "lan_block_google_dns_ips" nft_ac_add "lan_block_google_dns_ips" "lan_block_google_dns_ipv6s"
   fi
   if [ -n "$(uci -q get openclash.config.lan_block_google_dns_macs)" ]; then
      nft 'add set inet fw4 lan_block_google_dns_macs { type ether_addr; }'
      config_load "openclash"
      config_list_foreach "config" "lan_block_google_dns_macs" nft_ac_add "lan_block_google_dns_macs"
   fi

   #lan_ac
   if [ "$lan_ac_mode" = "0" ]; then
      if [ -n "$(uci -q get openclash.config.lan_ac_black_ips)" ]; then
         nft 'add set inet fw4 lan_ac_black_ips { type ipv4_addr; flags interval; auto-merge; }'
         nft 'add set inet fw4 lan_ac_black_ipv6s { type ipv6_addr; flags interval; auto-merge; }'
         config_load "openclash"
         config_list_foreach "config" "lan_ac_black_ips" nft_ac_add "lan_ac_black_ips" "lan_ac_black_ipv6s"
      fi
      if [ -n "$(uci -q get openclash.config.lan_ac_black_macs)" ]; then
         nft 'add set inet fw4 lan_ac_black_macs { type ether_addr; }'
         config_load "openclash"
         config_list_foreach "config" "lan_ac_black_macs" nft_ac_add "lan_ac_black_macs"
      fi
   elif [ "$lan_ac_mode" = "1" ]; then
      if [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ]; then
         nft 'add set inet fw4 lan_ac_white_ips { type ipv4_addr; flags interval; auto-merge; }'
         nft 'add set inet fw4 lan_ac_white_ipv6s { type ipv6_addr; flags interval; auto-merge; }'
         config_load "openclash"
         config_list_foreach "config" "lan_ac_white_ips" nft_ac_add "lan_ac_white_ips" "lan_ac_white_ipv6s"
      fi
      if [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
         nft 'add set inet fw4 lan_ac_white_macs { type ether_addr; }'
         config_load "openclash"
         config_list_foreach "config" "lan_ac_white_macs" nft_ac_add "lan_ac_white_macs"
      fi
   fi

   #wan ac
   if [ -n "$(uci -q get openclash.config.wan_ac_black_ips)" ]; then
      nft 'add set inet fw4 wan_ac_black_ips { type ipv4_addr; flags interval; auto-merge; }'
      nft 'add set inet fw4 wan_ac_black_ipv6s { type ipv6_addr; flags interval; auto-merge; }'
      config_load "openclash"
      config_list_foreach "config" "wan_ac_black_ips" nft_ac_add "wan_ac_black_ips" "wan_ac_black_ipv6s"
   fi

   #lan port ac
   if [ -n "$(uci -q get openclash.config.lan_ac_black_ports)" ]; then
      nft 'add set inet fw4 lan_ac_black_ports { type inet_service; }'
      config_load "openclash"
      config_list_foreach "config" "lan_ac_black_ports" nft_ac_add "lan_ac_black_ports"
   fi

   #local
   nft 'add set inet fw4 localnetwork { type ipv4_addr; flags interval; auto-merge; }'
   #nft 'delete set inet fw4 localnetwork'
   if [ -f "/etc/openclash/custom/openclash_custom_localnetwork_ipv4.list" ]; then
      for line in `cat "/etc/openclash/custom/openclash_custom_localnetwork_ipv4.list"`
      do
         nft add element inet fw4 localnetwork { "$line" }
      done
   else
      nft 'add element inet fw4 localnetwork { 0.0.0.0/8, 127.0.0.0/8, 10.0.0.0/8, 169.254.0.0/16, 192.168.0.0/16, 224.0.0.0/4, 240.0.0.0/4, 172.16.0.0/12, 100.64.0.0/10}'
   fi

   if [ -n "$wan_ip4s" ]; then
      for wan_ip4 in $wan_ip4s; do
         nft add element inet fw4 localnetwork { "$wan_ip4" }
      done
   fi

   #common ports
   if [ -n "$common_ports" ] && [ "$common_ports" != "0" ]; then
      nft 'add set inet fw4 common_ports { type inet_service; }'
      for i in $common_port; do
         nft add element inet fw4 common_ports { "$i" }
      done
   fi

   #bypass gateway compatible
   if [ "$bypass_gateway_compatible" -eq 1 ]; then
      #nft 'delete chain inet fw4 openclash_post'
      nft 'add chain inet fw4 openclash_post'
      nft 'flush chain inet fw4 openclash_post'
      nft 'add rule inet fw4 openclash_post ip saddr @localnetwork tcp sport @lan_ac_black_ports counter return'
      nft add rule inet fw4 openclash_post meta mark "$PROXY_FWMARK" counter accept
      nft 'add rule inet fw4 openclash_post ip daddr @localnetwork counter return'
      nft 'add rule inet fw4 openclash_post meta nfproto {ipv4} fib saddr type != { local } meta skuid != 65534 counter masquerade'
      nft add rule inet fw4 srcnat meta nfproto {ipv4} counter jump openclash_post comment \"OpenClash Bypass Gateway Compatible\"
   fi

   #intranet allowed
   if [ "$intranet_allowed" -eq 1 ]; then
      wan_ints=$(nft list chain inet fw4 input |grep -e "jump input_wan" 2>/dev/null |awk '{for (i=1;i<=NF;i++){if ($i ~ /iifname/ && $(i+1) != "{") {print $(i+1)} if ($i ~ /iifname/ && $(i+1) == "{"){for (j=i+1;j<=NF;j++){if ($j~ /}/) {out="";for (k=i+1;k<=j;k++){out=out" "$k};print out}}}}}' 2>/dev/null |sed 's/"//g'|sed 's/{//g'|sed 's/}//g'|sed 's/,//g')
      if [ -n "$wan_ints" ]; then
         nft 'add chain inet fw4 openclash_wan_input'
         nft 'flush chain inet fw4 openclash_wan_input'
         for wan_int in $wan_ints; do
            #nft delete rule inet fw4 input $(nft -a list chain inet fw4 input |grep "@localnetwork" |awk -F '# ' '{print$2}')
            nft insert rule inet fw4 input position 0 iifname "$wan_int" ip saddr != @localnetwork counter jump openclash_wan_input
         done
         nft add rule inet fw4 openclash_wan_input udp dport {$proxy_port,$tproxy_port,$cn_port,$http_port,$socks_port,$mixed_port,$dns_port} counter reject
         nft add rule inet fw4 openclash_wan_input tcp dport {$proxy_port,$tproxy_port,$cn_port,$http_port,$socks_port,$mixed_port,$dns_port} counter reject
      else
         LOG_OUT "Warning: Can't Settting Only Intranet Allowed Function, Get IPv4 WAN Interfaces error, Please Verify The Firewall's WAN Zone Name is wan, Ignore This IF The Device Does not Have a WAN Interfaces..."
      fi
   fi

   DNSPORT=$(uci -q get dhcp.@dnsmasq[0].port)
   if [ -z "$DNSPORT" ]; then
      DNSPORT=$(netstat -nlp |grep -E '127.0.0.1:.*dnsmasq' |awk -F '127.0.0.1:' '{print $2}' |awk '{print $1}' |head -1 || echo 53)
   fi

   if [ "$enable_redirect_dns" -eq 1 ]; then
      if [ -z "$(nft list chain inet fw4 dstnat |grep 'OpenClash DNS Hijack')" ]; then
         if [ "$lan_ac_mode" != "1" ]; then
            ACBLACKDNSFILTER=""
            if [ "$lan_ac_mode" = "0" ]; then
               if [ -n "$(uci -q get openclash.config.lan_ac_black_ips)" ]; then
                  ACBLACKDNSFILTER="ip saddr != @lan_ac_black_ips"
               fi
               if [ -n "$(uci -q get openclash.config.lan_ac_black_macs)" ]; then
                  ACBLACKDNSFILTER="$ACBLACKDNSFILTER ether saddr != @lan_ac_black_macs"
               fi
            fi
            nft insert rule inet fw4 dstnat position 0 tcp dport 53 ${ACBLACKDNSFILTER} counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
            nft insert rule inet fw4 dstnat position 0 udp dport 53 ${ACBLACKDNSFILTER} counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
         else
            nft insert rule inet fw4 dstnat position 0 tcp dport 53 ip saddr @lan_ac_white_ips counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
            nft insert rule inet fw4 dstnat position 0 udp dport 53 ip saddr @lan_ac_white_ips counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
            nft insert rule inet fw4 dstnat position 0 tcp dport 53 ether saddr @lan_ac_white_macs counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
            nft insert rule inet fw4 dstnat position 0 udp dport 53 ether saddr @lan_ac_white_macs counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
         fi
      fi
   elif [ "$enable_redirect_dns" -eq 2 ]; then
      nft 'add chain inet fw4 openclash_dns_redirect'
      if [ "$lan_ac_mode" != "1" ]; then
         ACBLACKDNSFILTER=""
         if [ "$lan_ac_mode" = "0" ]; then
            if [ -n "$(uci -q get openclash.config.lan_ac_black_ips)" ]; then
               ACBLACKDNSFILTER="ip saddr != @lan_ac_black_ips"
            fi
            if [ -n "$(uci -q get openclash.config.lan_ac_black_macs)" ]; then
               ACBLACKDNSFILTER="$ACBLACKDNSFILTER ether saddr != @lan_ac_black_macs"
            fi
         fi
         nft add rule inet fw4 openclash_dns_redirect tcp dport 53 ${ACBLACKDNSFILTER} counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
         nft add rule inet fw4 openclash_dns_redirect udp dport 53 ${ACBLACKDNSFILTER} counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
      else
         nft add rule inet fw4 openclash_dns_redirect tcp dport 53 ip saddr @lan_ac_white_ips counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
         nft add rule inet fw4 openclash_dns_redirect udp dport 53 ip saddr @lan_ac_white_ips counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
         nft add rule inet fw4 openclash_dns_redirect tcp dport 53 ether saddr @lan_ac_white_macs counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
         nft add rule inet fw4 openclash_dns_redirect udp dport 53 ether saddr @lan_ac_white_macs counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
      fi
      nft 'insert rule inet fw4 dstnat position 0 tcp dport 53 counter jump openclash_dns_redirect'
      nft 'insert rule inet fw4 dstnat position 0 udp dport 53 counter jump openclash_dns_redirect'
      if [ "$router_self_proxy" = 1 ]; then
         nft 'add chain inet fw4 nat_output { type nat hook output priority -1; }'
         nft insert rule inet fw4 nat_output position 0 tcp dport 53 ip daddr {127.0.0.1} meta skuid != 65534 counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
         nft insert rule inet fw4 nat_output position 0 udp dport 53 ip daddr {127.0.0.1} meta skuid != 65534 counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
      fi
   fi

   if [ "$en_mode" = "fake-ip" ] && [ "$china_ip_route" = "1" ] && [ "$enable_redirect_dns" != "2" ]; then
      LOG_OUT "Tip: Bypass the China IP May Cause the Dnsmasq Load For a Long Time After Restart in FAKE-IP Mode, Hijack the DNS to Core Untill the Dnsmasq Works Well..."
      nft insert rule inet fw4 dstnat position 0 tcp dport 53 counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
      nft insert rule inet fw4 dstnat position 0 udp dport 53 counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
      nft 'add chain inet fw4 nat_output { type nat hook output priority -1; }'
      nft insert rule inet fw4 nat_output position 0 tcp dport 53 meta skuid != 65534 counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
      nft insert rule inet fw4 nat_output position 0 udp dport 53 meta skuid != 65534 counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
      nft insert rule inet fw4 nat_output position 0 tcp dport 12353 meta skuid != 65534 counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
      nft insert rule inet fw4 nat_output position 0 udp dport 12353 meta skuid != 65534 counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
   fi

   if [ -z "$en_mode_tun" ] || [ "$en_mode_tun" -eq 2 ]; then
      #tcp
      nft 'add chain inet fw4 openclash'
      nft 'flush chain inet fw4 openclash'
      nft add rule inet fw4 openclash ip daddr @localnetwork counter return
      if [ -z "$en_mode_tun" ] && [ "$en_mode" = "fake-ip" ]; then
          nft add rule inet fw4 openclash ip protocol tcp ip daddr { "$fakeip_range" } counter redirect to "$proxy_port"
      fi
      nft 'add rule inet fw4 openclash ip saddr @localnetwork tcp sport @lan_ac_black_ports counter return'
      nft 'add rule inet fw4 openclash ip daddr @wan_ac_black_ips counter return'
      nft 'add rule inet fw4 openclash ip saddr @lan_ac_black_ips counter return'
      nft 'add rule inet fw4 openclash ether saddr @lan_ac_black_macs counter return'
      if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
         nft 'add rule inet fw4 openclash ether saddr != @lan_ac_white_macs ip saddr != @lan_ac_white_ips counter return'
      else
         nft 'add rule inet fw4 openclash ether saddr != @lan_ac_white_macs counter return'
         nft 'add rule inet fw4 openclash ip saddr != @lan_ac_white_ips counter return'
      fi

      if [ "$en_mode" = "redir-host" ]; then
         nft 'add rule inet fw4 openclash tcp dport != @common_ports counter return'
      fi
      if [ "$china_ip_route" = "1" ]; then
         if [ "$enable_redirect_dns" != "2" ]; then
            nft 'add rule inet fw4 openclash ip daddr @china_ip_route ip daddr != @china_ip_route_pass counter return'
         else
            nft 'add rule inet fw4 openclash ip daddr @china_ip_route counter return'
         fi
      fi
      nft add rule inet fw4 openclash ip protocol tcp counter redirect to "$proxy_port"
      nft 'add rule inet fw4 dstnat meta nfproto {ipv4} ip protocol tcp counter jump openclash'
      if [ -z "$en_mode_tun" ]; then
         #Google dns
         nft insert rule inet fw4 dstnat position 0 ip daddr { 8.8.8.8, 8.8.4.4 } tcp dport 53 counter redirect to "$proxy_port" comment \"OpenClash Google DNS Hijack\"
         #udp
         if [ "$enable_udp_proxy" -eq 1 ]; then
            modprobe nft_tproxy >/dev/null 2>&1
            ip rule add fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE"
            ip route add local 0.0.0.0/0 dev lo table "$PROXY_ROUTE_TABLE"
            nft 'add chain inet fw4 openclash_mangle'
            nft 'flush chain inet fw4 openclash_mangle'
            nft 'add chain inet fw4 openclash_upnp'
            nft 'flush chain inet fw4 openclash_upnp'
            upnp_exclude
            nft 'add rule inet fw4 openclash_mangle meta l4proto { udp } iifname lo counter return'
            nft add rule inet fw4 openclash_mangle ip daddr @localnetwork counter return
            nft 'add rule inet fw4 openclash_mangle udp dport 53 counter return'
            if [ "$en_mode" = "fake-ip" ]; then
               nft add rule inet fw4 openclash_mangle meta l4proto { udp } ip daddr { "$fakeip_range" } mark set "$PROXY_FWMARK" tproxy ip to 127.0.0.1:"$tproxy_port" counter accept
            fi
            nft 'add rule inet fw4 openclash_mangle ip saddr @localnetwork udp sport @lan_ac_black_ports counter return'
            nft 'add rule inet fw4 openclash_mangle ip daddr @wan_ac_black_ips counter return'
            nft 'add rule inet fw4 openclash_mangle ip saddr @lan_ac_black_ips counter return'
            nft 'add rule inet fw4 openclash_mangle ether saddr @lan_ac_black_macs counter return'
            if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
               nft 'add rule inet fw4 openclash_mangle ether saddr != @lan_ac_white_macs ip saddr != @lan_ac_white_ips counter return'
            else
               nft 'add rule inet fw4 openclash_mangle ether saddr != @lan_ac_white_macs counter return'
               nft 'add rule inet fw4 openclash_mangle ip saddr != @lan_ac_white_ips counter return'
            fi

            if [ "$en_mode" = "redir-host" ]; then
               nft 'add rule inet fw4 openclash_mangle udp dport != @common_ports counter return'
            fi
            if [ "$china_ip_route" = "1" ]; then
               if [ "$enable_redirect_dns" != "2" ]; then
                  nft 'add rule inet fw4 openclash_mangle ip daddr @china_ip_route ip daddr != @china_ip_route_pass counter return'
               else
                  nft 'add rule inet fw4 openclash_mangle ip daddr @china_ip_route counter return'
               fi
            fi

            nft 'add rule inet fw4 openclash_mangle ip protocol udp counter jump openclash_upnp'

            nft add rule inet fw4 openclash_mangle meta l4proto { udp } mark set "$PROXY_FWMARK" tproxy ip to 127.0.0.1:"$tproxy_port" counter accept
            nft 'add rule inet fw4 mangle_prerouting meta nfproto {ipv4} ip protocol udp counter jump openclash_mangle'

         elif [ "$en_mode" = "fake-ip" ]; then
            modprobe nft_tproxy >/dev/null 2>&1
            ip rule add fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE"
            ip route add local 0.0.0.0/0 dev lo table "$PROXY_ROUTE_TABLE"
            nft 'add chain inet fw4 openclash_mangle'
            nft 'flush chain inet fw4 openclash_mangle'
            nft 'add rule inet fw4 openclash_mangle meta l4proto { udp } iifname lo counter return'
            nft add rule inet fw4 openclash_mangle meta l4proto { udp } ip daddr { "$fakeip_range" } mark set "$PROXY_FWMARK" tproxy ip to 127.0.0.1:"$tproxy_port" counter accept 2>/dev/null
            nft 'add rule inet fw4 mangle_prerouting meta nfproto {ipv4} ip protocol udp counter jump openclash_mangle'

            if [ "$router_self_proxy" = "1" ] || ([ "$enable_redirect_dns" != "2" ] && [ "$en_mode" = "fake-ip" ]); then
               nft 'add chain inet fw4 openclash_mangle_output'
               nft 'flush chain inet fw4 openclash_mangle_output'
               nft add rule inet fw4 openclash_mangle_output meta l4proto { udp } ip daddr { "$fakeip_range" } mark set "$PROXY_FWMARK" counter
               nft 'add rule inet fw4 mangle_output meta nfproto {ipv4} ip protocol udp counter jump openclash_mangle_output'
            fi
         fi

         #quic
         if [ "$disable_udp_quic" -eq 1 ]; then
            nft insert rule inet fw4 input position 0 udp dport 443 ip daddr != @china_ip_route counter reject comment \"OpenClash QUIC REJECT\"
         fi
      fi

      if [ "$router_self_proxy" = "1" ] || ([ "$enable_redirect_dns" != "2" ] && [ "$en_mode" = "fake-ip" ]); then
         nft 'add chain inet fw4 openclash_output'
         nft 'flush chain inet fw4 openclash_output'
         nft 'add rule inet fw4 openclash_output ip daddr @localnetwork counter return'
         nft 'add rule inet fw4 openclash_output ip saddr @localnetwork tcp sport @lan_ac_black_ports counter return'

         if [ "$en_mode" = "fake-ip" ] && [ "$en_mode_tun" != "1" ]; then
            nft add rule inet fw4 openclash_output ip protocol tcp ip daddr { "$fakeip_range" } skuid != 65534 counter redirect to "$proxy_port"
         fi
         if [ "$router_self_proxy" = "1" ]; then
            nft 'add rule inet fw4 openclash_output skuid != 65534 ip daddr @wan_ac_black_ips counter return'
            if [ "$en_mode" = "redir-host" ]; then
               nft add rule inet fw4 openclash_output tcp dport != @common_ports skuid != 65534 counter return
            fi
            if [ "$china_ip_route" = "1" ]; then
               if [ "$enable_redirect_dns" != "2" ]; then
                  nft 'add rule inet fw4 openclash_output skuid != 65534 ip daddr @china_ip_route ip daddr != @china_ip_route_pass counter return'
               else
                  nft 'add rule inet fw4 openclash_output skuid != 65534 ip daddr @china_ip_route counter return'
               fi
            fi
            nft add rule inet fw4 openclash_output ip protocol tcp skuid != 65534 counter redirect to "$proxy_port"
         fi
         nft 'add chain inet fw4 nat_output { type nat hook output priority -1; }'
         nft 'add rule inet fw4 nat_output meta nfproto {ipv4} ip protocol tcp counter jump openclash_output'
      fi
   fi

   if [ -n "$en_mode_tun" ]; then
      #TUN模式
      #启动TUN
      set_tun_tap

      #设置防火墙
      if [ "$router_self_proxy" = "1" ] || ([ "$enable_redirect_dns" != "2" ] && [ "$en_mode" = "fake-ip" ]); then
         nft 'add chain inet fw4 openclash_mangle_output'
         nft 'flush chain inet fw4 openclash_mangle_output'
         nft 'add rule inet fw4 openclash_mangle_output ip daddr @localnetwork counter return'
         nft 'add rule inet fw4 openclash_mangle_output ip saddr @localnetwork meta l4proto {tcp,udp} th sport @lan_ac_black_ports counter return'
         if [ "$en_mode" = "fake-ip" ]; then
            if [ "$en_mode_tun" -eq 1 ]; then
               nft add rule inet fw4 openclash_mangle_output meta l4proto {tcp,udp} th dport { 0-65535 } ip daddr { "$fakeip_range" } mark set "$PROXY_FWMARK" counter
               if [ "$router_self_proxy" = "1" ]; then
                  nft 'add rule inet fw4 openclash_mangle_output skuid != 65534 ip daddr @wan_ac_black_ips counter return'
                  if [ "$china_ip_route" = "1" ]; then
                     if [ "$enable_redirect_dns" != "2" ]; then
                        nft 'add rule inet fw4 openclash_mangle_output skuid != 65534 ip daddr @china_ip_route ip daddr != @china_ip_route_pass counter return'
                     else
                        nft 'add rule inet fw4 openclash_mangle_output skuid != 65534 ip daddr @china_ip_route counter return'
                     fi
                  fi
                  nft add rule inet fw4 openclash_mangle_output tcp dport { 0-65535 } skuid != 65534 meta mark set "$PROXY_FWMARK" counter
               fi
            else
               nft add rule inet fw4 openclash_mangle_output skuid != 65534 udp dport { 0-65535 } ip daddr { "$fakeip_range" } meta mark set "$PROXY_FWMARK" counter
            fi
         elif [ "$en_mode" = "redir-host" ] && [ "$en_mode_tun" -eq 1 ]; then
            nft 'add rule inet fw4 openclash_mangle_output skuid != 65534 ip daddr @wan_ac_black_ips counter return'
            nft 'add rule inet fw4 openclash_mangle_output meta l4proto {tcp,udp} th dport != @common_ports skuid != 65534 counter return'
            if [ "$china_ip_route" = "1" ]; then
               if [ "$enable_redirect_dns" != "2" ]; then
                  nft 'add rule inet fw4 openclash_mangle_output skuid != 65534 ip daddr @china_ip_route ip daddr != @china_ip_route_pass counter return'
               else
                  nft 'add rule inet fw4 openclash_mangle_output skuid != 65534 ip daddr @china_ip_route counter return'
               fi
            fi
            nft add rule inet fw4 openclash_mangle_output tcp dport { 0-65535 } skuid != 65534 meta mark set "$PROXY_FWMARK" counter
         fi
         nft 'add rule inet fw4 mangle_output meta nfproto {ipv4} meta l4proto {tcp,udp} counter jump openclash_mangle_output'
      fi

      nft 'add chain inet fw4 openclash_mangle'
      nft 'flush chain inet fw4 openclash_mangle'
      nft 'add chain inet fw4 openclash_dns_hijack'
      nft 'flush chain inet fw4 openclash_dns_hijack'
      nft 'add chain inet fw4 openclash_upnp'
      nft 'flush chain inet fw4 openclash_upnp'
      upnp_exclude

      #其他流量
      nft 'add rule inet fw4 openclash_mangle meta l4proto {tcp,udp} iifname utun counter return'
      nft add rule inet fw4 openclash_mangle ip daddr @localnetwork counter return
      nft 'add rule inet fw4 openclash_mangle ip saddr @localnetwork meta l4proto {tcp,udp} th sport @lan_ac_black_ports counter return'
      nft 'add rule inet fw4 openclash_mangle ip daddr @wan_ac_black_ips counter return'
      nft 'add rule inet fw4 openclash_mangle ip saddr @lan_ac_black_ips counter return'
      nft 'add rule inet fw4 openclash_mangle ether saddr @lan_ac_black_macs counter return'
      if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
         nft 'add rule inet fw4 openclash_mangle ether saddr != @lan_ac_white_macs ip saddr != @lan_ac_white_ips counter return'
      else
         nft 'add rule inet fw4 openclash_mangle ether saddr != @lan_ac_white_macs counter return'
         nft 'add rule inet fw4 openclash_mangle ip saddr != @lan_ac_white_ips counter return'
      fi

      if [ "$en_mode" = "redir-host" ]; then
         nft 'add rule inet fw4 openclash_mangle meta l4proto {tcp,udp} th dport != @common_ports counter return'
      fi
      if [ "$china_ip_route" = "1" ]; then
         if [ "$enable_redirect_dns" != "2" ]; then
            nft 'add rule inet fw4 openclash_mangle ip daddr @china_ip_route ip daddr != @china_ip_route_pass counter return'
         else
            nft 'add rule inet fw4 openclash_mangle ip daddr @china_ip_route counter return'
         fi
      fi
      nft 'add rule inet fw4 openclash_mangle ip protocol udp counter jump openclash_upnp'
      nft add rule inet fw4 openclash_mangle meta l4proto {tcp,udp} th dport { 0-65535 } mark set "$PROXY_FWMARK" counter

      if [ "$en_mode_tun" -eq 1 ]; then
         nft 'insert rule inet fw4 mangle_prerouting position 0 meta nfproto {ipv4} meta l4proto {tcp,udp} counter jump openclash_mangle'
      else
         if [ "$enable_redirect_dns" -eq 1 ]; then
            nft 'insert rule inet fw4 mangle_prerouting position 0 meta nfproto {ipv4} tcp dport 53 counter jump openclash_dns_hijack'
            nft 'add rule inet fw4 openclash_dns_hijack ip saddr @lan_ac_black_ips counter return'
            nft 'add rule inet fw4 openclash_dns_hijack ether saddr @lan_ac_black_macs counter return'
            if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
               nft 'add rule inet fw4 openclash_dns_hijack ether saddr != @lan_ac_white_macs ip saddr != @lan_ac_white_ips counter return'
            else
               nft 'add rule inet fw4 openclash_dns_hijack ether saddr != @lan_ac_white_macs counter return'
               nft 'add rule inet fw4 openclash_dns_hijack ip saddr != @lan_ac_white_ips counter return'
            fi
            nft add rule inet fw4 openclash_dns_hijack meta nfproto {ipv4} tcp dport 53 mark set "$PROXY_FWMARK" comment \"OpenClash TCP DNS Hijack\" counter
         fi
         nft 'insert rule inet fw4 mangle_prerouting position 0 meta nfproto {ipv4} ip protocol udp counter jump openclash_mangle'
      fi

      if [ "$enable_redirect_dns" -eq 2 ]; then
         local position=$(nft -a list chain inet fw4 openclash_dns_redirect |grep "DNS" |grep -v "redirect" |awk -F '# handle ' '{print$2}' |sort -rn |head -1)
         [ -z "$position" ] && position=0
         nft insert rule inet fw4 openclash_dns_redirect position "$position" meta nfproto {ipv4} tcp dport 53 counter accept comment \"OpenClash TCP DNS Hijack\"
      elif [ "$enable_redirect_dns" -eq 1 ]; then
         nft insert rule inet fw4 dstnat position 0 meta nfproto {ipv4} tcp dport 53 counter accept comment \"OpenClash TCP DNS Hijack\"
      fi

      #TUN FORWORD
      nft insert rule inet fw4 forward position 0 meta l4proto {tcp,udp} oifname utun counter accept comment \"OpenClash TUN Forward\"

      #quic
      if [ "$disable_udp_quic" -eq 1 ]; then
         nft insert rule inet fw4 forward position 0 oifname utun udp dport 443 ip daddr != @china_ip_route counter reject comment \"OpenClash QUIC REJECT\"
      fi
   fi

   #google_dns_block
   if [ -n "$(uci -q get openclash.config.lan_block_google_dns_ips)" ] || [ -n "$(uci -q get openclash.config.lan_block_google_dns_macs)" ]; then
      nft 'add set inet fw4 openclash_google_dns_ips { type ipv4_addr; flags interval; auto-merge; }'
      nft 'add element inet fw4 openclash_google_dns_ips { 8.8.8.8, 8.8.4.4 }'
      if [ -z "$en_mode_tun" ] || [ "$en_mode_tun" -eq 2 ]; then
         nft insert rule inet fw4 dstnat position 0 ip saddr @lan_block_google_dns_ips ip daddr @openclash_google_dns_ips counter accept comment \"OpenClash Google DNS Block\"
         nft insert rule inet fw4 dstnat position 0 ether saddr @lan_block_google_dns_macs ip daddr @openclash_google_dns_ips counter accept comment \"OpenClash Google DNS Block\"
      fi
      nft insert rule inet fw4 forward position 0 ip saddr @lan_block_google_dns_ips ip daddr @openclash_google_dns_ips counter reject comment \"OpenClash Google DNS Block\"
      nft insert rule inet fw4 forward position 0 ether saddr @lan_block_google_dns_macs ip daddr @openclash_google_dns_ips counter reject comment \"OpenClash Google DNS Block\"
   fi

   #ipv6
   if [ "$ipv6_enable" -eq 1 ]; then
      if [ -z "$(nft list chain inet fw4 dstnat |grep 'OpenClash DNS Hijack')" ]; then
         if [ "$enable_redirect_dns" -eq 1 ]; then
            if [ "$lan_ac_mode" != "1" ]; then
               ACBLACKDNSFILTER=""
               if [ "$lan_ac_mode" = "0" ]; then
                  if [ -n "$(uci -q get openclash.config.lan_ac_black_ips)" ]; then
                     ACBLACKDNSFILTER="ip6 saddr != @lan_ac_black_ipv6s"
                  fi
                  if [ -n "$(uci -q get openclash.config.lan_ac_black_macs)" ]; then
                     ACBLACKDNSFILTER="$ACBLACKDNSFILTER ether saddr != @lan_ac_black_macs"
                  fi
               fi
               nft insert rule inet fw4 dstnat position 0 meta nfproto {ipv6} tcp dport 53 ${ACBLACKDNSFILTER} counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
               nft insert rule inet fw4 dstnat position 0 meta nfproto {ipv6} udp dport 53 ${ACBLACKDNSFILTER} counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
            else
               nft insert rule inet fw4 dstnat position 0 meta nfproto {ipv6} tcp dport 53 ip6 saddr @lan_ac_white_ipv6s counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
               nft insert rule inet fw4 dstnat position 0 meta nfproto {ipv6} udp dport 53 ip6 saddr @lan_ac_white_ipv6s counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
               nft insert rule inet fw4 dstnat position 0 meta nfproto {ipv6} tcp dport 53 ether saddr @lan_ac_white_macs counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
               nft insert rule inet fw4 dstnat position 0 meta nfproto {ipv6} udp dport 53 ether saddr @lan_ac_white_macs counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
            fi
         elif [ "$enable_redirect_dns" -eq 2 ]; then
            if [ "$lan_ac_mode" != "1" ]; then
               ACBLACKDNSFILTER=""
               if [ "$lan_ac_mode" = "0" ]; then
                  if [ -n "$(uci -q get openclash.config.lan_ac_black_ips)" ]; then
                     ACBLACKDNSFILTER="ip6 saddr != @lan_ac_black_ipv6s"
                  fi
                  if [ -n "$(uci -q get openclash.config.lan_ac_black_macs)" ]; then
                     ACBLACKDNSFILTER="$ACBLACKDNSFILTER ether saddr != @lan_ac_black_macs"
                  fi
               fi
               nft add rule inet fw4 openclash_dns_redirect meta nfproto {ipv6} tcp dport 53 ${ACBLACKDNSFILTER} counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
               nft add rule inet fw4 openclash_dns_redirect meta nfproto {ipv6} udp dport 53 ${ACBLACKDNSFILTER} counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
            else
               nft add rule inet fw4 openclash_dns_redirect meta nfproto {ipv6} tcp dport 53 ip6 saddr @lan_ac_white_ipv6s counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
               nft add rule inet fw4 openclash_dns_redirect meta nfproto {ipv6} udp dport 53 ip6 saddr @lan_ac_white_ipv6s counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
               nft add rule inet fw4 openclash_dns_redirect meta nfproto {ipv6} tcp dport 53 ether saddr @lan_ac_white_macs counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
               nft add rule inet fw4 openclash_dns_redirect meta nfproto {ipv6} udp dport 53 ether saddr @lan_ac_white_macs counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
            fi
            nft 'insert rule inet fw4 dstnat position 0 meta nfproto {ipv6} tcp dport 53 counter jump openclash_dns_redirect'
            nft 'insert rule inet fw4 dstnat position 0 meta nfproto {ipv6} udp dport 53 counter jump openclash_dns_redirect'
            if [ "$router_self_proxy" = 1 ]; then
               nft 'add chain inet fw4 nat_output { type nat hook output priority -1; }'
               nft insert rule inet fw4 nat_output position 0 meta nfproto {ipv6} tcp dport 53 ip6 daddr {::/0} meta skuid != 65534 counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
               nft insert rule inet fw4 nat_output position 0 meta nfproto {ipv6} udp dport 53 ip6 daddr {::/0} meta skuid != 65534 counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
            fi
         fi
      fi
      if [ "$en_mode" = "fake-ip" ] && [ "$china_ip_route" = "1" ] && [ "$enable_redirect_dns" != "2" ]; then
         nft insert rule inet fw4 dstnat position 0 meta nfproto {ipv6} tcp dport 53 counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
         nft insert rule inet fw4 dstnat position 0 meta nfproto {ipv6} udp dport 53 counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
         nft 'add chain inet fw4 nat_output { type nat hook output priority -1; }'
         nft add rule inet fw4 nat_output position 0 meta nfproto {ipv6} tcp dport 53 meta skuid != 65534 counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
         nft add rule inet fw4 nat_output position 0 meta nfproto {ipv6} udp dport 53 meta skuid != 65534 counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
         nft add rule inet fw4 nat_output position 0 meta nfproto {ipv6} tcp dport 12353 meta skuid != 65534 counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
         nft add rule inet fw4 nat_output position 0 meta nfproto {ipv6} udp dport 12353 meta skuid != 65534 counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
      fi

      if [ "$china_ip6_route" = "1" ] || [ "$disable_udp_quic" = "1" ]; then
         nft 'flush set inet fw4 china_ip6_route'
         nft -f '/etc/openclash/china_ip6_route.ipset'
         CHNROUTE_WAIT=0
         while ( [ -z "$(nft list sets |grep "set china_ip6_route {")" ] && [ "$CHNROUTE_WAIT" -le 3 ] )
         do
            nft -f '/etc/openclash/china_ip6_route.ipset'
         done

         if [ "$enable_redirect_dns" != "2" ]; then
            mkdir -p ${DNSMASQ_CONF_DIR}

            echo "add set inet fw4 china_ip6_route_pass { type ipv6_addr; flags interval; auto-merge; }" >>/tmp/openclash_china_ip6_route_pass.list
            [ -z `(awk '!/^$/&&!/^#/&&!/^(\*?\.?)*[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})*$/{printf("    %s,'" "'\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute6_pass.list)` ] || {
               echo "define china_ip6_route_pass = {" >/tmp/openclash_china_ip6_route_pass.list
               awk '!/^$/&&!/^#/&&!/^(\*?\.?)*[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})*$/{printf("    %s,'" "'\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute6_pass.list >>/tmp/openclash_china_ip6_route_pass.list 2>/dev/null
               echo "}" >>/tmp/openclash_china_ip6_route_pass.list
               echo 'add element inet fw4 china_ip6_route_pass $china_ip6_route_pass' >>/tmp/openclash_china_ip6_route_pass.list
            }
            awk '!/^$/&&!/^#/&&/^(\*?\.?)*[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})*$/{printf("'${settype}'=/%s/'${nftflag}'china_ip_route_pass'" "'\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute6_pass.list >>${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf 2>/dev/null

            nft 'flush set inet fw4 china_ip6_route_pass'
            nft -f '/tmp/openclash_china_ip6_route_pass.list'
            rm -rf /tmp/openclash_china_ip6_route_pass.list

            #Prevent domain repeat
            for i in `grep -wf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute_pass.conf`
            do
               if [ -n "$nftflag" ]; then
                  sed -i "s:${i}:${i},6#${nftflag}china_ip6_route_pass:g" ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute_pass.conf
               else
                  sed -i "s:${i}:${i},china_ip6_route_pass:g" ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute_pass.conf
               fi
               sed -i 's:'$i':EXCLUSIVE:;/EXCLUSIVE/d' ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf
            done
            if [ -n "$nftflag" ]; then
               sed -i "s/\/${nftflag}/\/4#${nftflag}/g" ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute_pass.conf
               sed -i "s/${nftflag}china_ip_route_pass/6#${nftflag}china_ip6_route_pass/g" ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf
            else
               sed -i "s/china_ip_route_pass/china_ip6_route_pass/g" ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf
            fi
         fi
      fi

      #local
      nft 'add set inet fw4 localnetwork6 { type ipv6_addr; flags interval; auto-merge; }'
      #nft 'delete set inet fw4 localnetwork6'
      if [ -f "/etc/openclash/custom/openclash_custom_localnetwork_ipv6.list" ]; then
         for line in `cat "/etc/openclash/custom/openclash_custom_localnetwork_ipv6.list"`
         do
            nft add element inet fw4 localnetwork6 { "$line" }
         done
      else
         nft 'add element inet fw4 localnetwork6 { ::/128, ::1/128, ::ffff:0:0/96, ::ffff:0:0:0/96, 64:ff9b::/96, 100::/64, 2001::/32, 2001:20::/28, 2001:db8::/32, 2002::/16, fc00::/7, fe80::/10, ff00::/8}'
      fi

      if [ -n "$wan_ip6s" ]; then
         for wan_ip6 in $wan_ip6s; do
            nft add element inet fw4 localnetwork6 { "$wan_ip6" }
         done
      fi

      #Google dns
      nft insert rule inet fw4 dstnat position 0 ip6 daddr { 2001:4860:4860::8888, 2001:4860:4860::8844 } tcp dport 53 counter accept comment \"OpenClash Google DNS Hijack\"

      if [ "$ipv6_mode" -eq 1 ]; then
         #tcp
         nft 'add chain inet fw4 openclash_v6'
         nft 'flush chain inet fw4 openclash_v6'
         nft add rule inet fw4 openclash_v6 ip6 daddr @localnetwork6 counter return
         nft 'add rule inet fw4 openclash_v6 ip6 saddr @localnetwork6 meta nfproto {ipv6} sport @lan_ac_black_ports counter return'
         nft 'add rule inet fw4 openclash_v6 ip6 daddr @wan_ac_black_ipv6s counter return'
         nft 'add rule inet fw4 openclash_v6 ip6 saddr @lan_ac_black_ipv6s counter return'
         nft 'add rule inet fw4 openclash_v6 ether saddr @lan_ac_black_macs counter return'
         if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
            nft 'add rule inet fw4 openclash_v6 ether saddr != @lan_ac_white_macs ip6 saddr != @lan_ac_white_ipv6s counter return'
         else
            nft 'add rule inet fw4 openclash_v6 ether saddr != @lan_ac_white_macs counter return'
            nft 'add rule inet fw4 openclash_v6 ip6 saddr != @lan_ac_white_ipv6s counter return'
         fi

         if [ "$en_mode" = "redir-host" ]; then
            nft 'add rule inet fw4 openclash_v6 meta nfproto {ipv6} th dport != @common_ports counter return'
         fi

         if [ "$china_ip6_route" = "1" ]; then
            if [ "$enable_redirect_dns" != "2" ]; then
               nft 'add rule inet fw4 openclash_v6 ip6 daddr @china_ip6_route ip6 daddr != @china_ip6_route_pass counter return'
            else
               nft 'add rule inet fw4 openclash_v6 ip6 daddr @china_ip6_route counter return'
            fi
         fi
         nft add rule inet fw4 openclash_v6 meta nfproto {ipv6} tcp dport { 0-65535 } counter redirect to "$proxy_port"
         nft 'add rule inet fw4 dstnat meta nfproto {ipv6} tcp dport { 0-65535 } counter jump openclash_v6'

         if [ "$router_self_proxy" = "1" ]; then
            nft 'add chain inet fw4 openclash_output_v6'
            nft 'flush chain inet fw4 openclash_output_v6'
            nft 'add rule inet fw4 openclash_output_v6 ip6 daddr @localnetwork6 counter return'
            nft 'add rule inet fw4 openclash_output_v6 ip6 saddr @localnetwork6 meta nfproto {ipv6} sport @lan_ac_black_ports counter return'
            nft 'add rule inet fw4 openclash_output_v6 skuid != 65534 ip6 daddr @wan_ac_black_ipv6s counter return'
            if [ "$en_mode" = "redir-host" ]; then
               nft 'add rule inet fw4 openclash_output_v6 meta nfproto {ipv6} th dport != @common_ports skuid != 65534 counter return'
            fi

            if [ "$china_ip6_route" = "1" ]; then
               if [ "$enable_redirect_dns" != "2" ]; then
                  nft 'add rule inet fw4 openclash_output_v6 skuid != 65534 ip6 daddr @china_ip6_route ip6 daddr != @china_ip6_route_pass counter return'
               else
                  nft 'add rule inet fw4 openclash_output_v6 skuid != 65534 ip6 daddr @china_ip6_route counter return'
               fi
            fi
            if [ "$ipv6_mode" -eq 2 ]; then
               nft add rule inet fw4 openclash_output_v6 meta nfproto {ipv6} skuid != 65534 tcp dport { 0-65535 } mark set "$PROXY_FWMARK" counter
            elif [ "$ipv6_mode" -eq 0 ]; then
               nft add rule inet fw4 openclash_output_v6 meta nfproto {ipv6} skuid != 65534 tcp dport { 0-65535 } mark set "$PROXY_FWMARK" tproxy ip6 to :"$tproxy_port" counter accept comment \"OpenClash TCP Tproxy\"
            fi
            nft 'add chain inet fw4 nat_output { type nat hook output priority -1; }'
            nft 'add rule inet fw4 nat_output meta nfproto {ipv6} ip protocol tcp counter jump openclash_output_v6'
         fi
      fi

      if [ "$enable_v6_udp_proxy" -eq 1 ] || [ "$ipv6_mode" -eq 0 ] || [ "$ipv6_mode" -eq 2 ]; then
         nft 'add chain inet fw4 openclash_mangle_v6'
         nft 'flush chain inet fw4 openclash_mangle_v6'
         nft 'add rule inet fw4 openclash_mangle_v6 meta nfproto {ipv6} udp iifname lo counter return'
         nft add rule inet fw4 openclash_mangle_v6 ip6 daddr @localnetwork6 counter return
         nft 'add rule inet fw4 openclash_mangle_v6 meta nfproto {ipv6} udp dport 53 counter return'
         nft 'add rule inet fw4 openclash_mangle_v6 ip6 saddr @localnetwork6 meta nfproto {ipv6} sport @lan_ac_black_ports counter return'
         nft 'add rule inet fw4 openclash_mangle_v6 ip6 daddr @wan_ac_black_ipv6s counter return'

         if [ "$en_mode" == "redir-host" ]; then
            nft 'add rule inet fw4 openclash_mangle_v6 meta nfproto {ipv6} th dport != @common_ports counter return'
         fi

         nft 'add rule inet fw4 openclash_mangle_v6 ip6 saddr @lan_ac_black_ipv6s counter return'
         nft 'add rule inet fw4 openclash_mangle_v6 ether saddr @lan_ac_black_macs counter return'
         if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
            nft 'add rule inet fw4 openclash_mangle_v6 ether saddr != @lan_ac_white_macs ip6 saddr != @lan_ac_white_ipv6s counter return'
         else
            nft 'add rule inet fw4 openclash_mangle_v6 ether saddr != @lan_ac_white_macs counter return'
            nft 'add rule inet fw4 openclash_mangle_v6 ip6 saddr != @lan_ac_white_ipv6s counter return'
         fi

         if [ "$china_ip6_route" = "1" ]; then
            if [ "$enable_redirect_dns" != "2" ]; then
               nft 'add rule inet fw4 openclash_mangle_v6 ip6 daddr @china_ip6_route ip6 daddr != @china_ip6_route_pass counter return'
            else
               nft 'add rule inet fw4 openclash_mangle_v6 ip6 daddr @china_ip6_route counter return'
            fi
         fi
      fi

      #TProxy & TUN
      if [ "$ipv6_mode" -ne 1 ]; then
         if [ "$ipv6_mode" -eq 0 ]; then
            nft add rule inet fw4 openclash_mangle_v6 meta nfproto {ipv6} tcp dport { 0-65535 } mark set "$PROXY_FWMARK" tproxy ip6 to :"$tproxy_port" counter accept comment \"OpenClash TCP Tproxy\"
         elif [ "$ipv6_mode" -eq 2 ]; then
            nft add rule inet fw4 openclash_mangle_v6 meta nfproto {ipv6} tcp dport { 0-65535 } mark set "$PROXY_FWMARK" counter
         fi

         if [ "$router_self_proxy" = "1" ]; then
            nft 'add chain inet fw4 openclash_mangle_output_v6'
            nft 'flush chain inet fw4 openclash_mangle_output_v6'
            nft 'add rule inet fw4 openclash_mangle_output_v6 ip6 daddr @localnetwork6 counter return'
            nft 'add rule inet fw4 openclash_mangle_output_v6 ip6 saddr @localnetwork6 meta nfproto {ipv6} sport @lan_ac_black_ports counter return'
            nft 'add rule inet fw4 openclash_mangle_output_v6 skuid != 65534 ip6 daddr @wan_ac_black_ipv6s counter return'
            if [ "$en_mode" = "redir-host" ]; then
               nft 'add rule inet fw4 openclash_mangle_output_v6 meta nfproto {ipv6} th dport != @common_ports skuid != 65534 counter return'
            fi

            if [ "$china_ip6_route" = "1" ]; then
               if [ "$enable_redirect_dns" != "2" ]; then
                  nft 'add rule inet fw4 openclash_mangle_output_v6 skuid != 65534 ip6 daddr @china_ip6_route ip6 daddr != @china_ip6_route_pass counter return'
               else
                  nft 'add rule inet fw4 openclash_mangle_output_v6 skuid != 65534 ip6 daddr @china_ip6_route counter return'
               fi
            fi
            if [ "$ipv6_mode" -eq 2 ]; then
               nft add rule inet fw4 openclash_mangle_output_v6 meta nfproto {ipv6} skuid != 65534 tcp dport { 0-65535 } mark set "$PROXY_FWMARK" counter
            elif [ "$ipv6_mode" -eq 0 ]; then
               nft add rule inet fw4 openclash_mangle_output_v6 meta nfproto {ipv6} skuid != 65534 tcp dport { 0-65535 } mark set "$PROXY_FWMARK" tproxy ip6 to :"$tproxy_port" counter accept comment \"OpenClash TCP Tproxy\"
            fi
            nft 'add rule inet fw4 mangle_output meta nfproto {ipv6} counter jump openclash_mangle_output_v6'
         fi
      fi

      #udp
      if [ "$ipv6_mode" -eq 2 ]; then
         nft add rule inet fw4 openclash_mangle_v6 meta nfproto {ipv6} udp dport { 0-65535 } mark set "$PROXY_FWMARK" counter
      else
         if [ "$enable_v6_udp_proxy" -eq 1 ]; then
            nft add rule inet fw4 openclash_mangle_v6 meta nfproto {ipv6} udp dport { 0-65535 } mark set "$PROXY_FWMARK" tproxy ip6 to :"$tproxy_port" counter accept comment \"OpenClash UDP Tproxy\"
         fi
      fi

      nft 'add rule inet fw4 mangle_prerouting meta nfproto {ipv6} counter jump openclash_mangle_v6'

      #route
      if [ "$ipv6_mode" -ne 2 ]; then
         if [ "$enable_v6_udp_proxy" -eq 1 ] || [ "$ipv6_mode" -eq 0 ]; then
            modprobe nft_tproxy >/dev/null 2>&1
            ip -6 rule add fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE"
            ip -6 route add local ::/0 dev lo table "$PROXY_ROUTE_TABLE"
         fi
      else
         set_tun_tap "v6"
      fi

      #quic
      if [ "$disable_udp_quic" -eq 1 ]; then
         nft insert rule inet fw4 input position 0 udp dport 443 ip6 daddr != @china_ip6_route counter reject comment \"OpenClash QUIC REJECT\"
      fi

      #bypass gateway compatible
      if [ "$bypass_gateway_compatible" -eq 1 ]; then
         #nft 'delete chain inet fw4 openclash_post_v6'
         nft 'add chain inet fw4 openclash_post_v6'
         nft 'flush chain inet fw4 openclash_post_v6'
         nft 'add rule inet fw4 openclash_post_v6 ip6 saddr @localnetwork6 meta nfproto {ipv6} sport @lan_ac_black_ports counter return'
         nft add rule inet fw4 openclash_post_v6 meta nfproto {ipv6} meta mark "$PROXY_FWMARK" counter accept
         nft 'add rule inet fw4 openclash_post_v6 ip6 daddr @localnetwork6 counter return'
         nft 'add rule inet fw4 openclash_post_v6 meta nfproto {ipv6} fib saddr type != { local } meta skuid != 65534 counter masquerade'
         nft add rule inet fw4 srcnat meta nfproto {ipv6} counter jump openclash_post_v6 comment \"OpenClash Bypass Gateway Compatible\"
      fi

      #google_dns_block
      if [ -n "$(uci -q get openclash.config.lan_block_google_dns_ips)" ] || [ -n "$(uci -q get openclash.config.lan_block_google_dns_macs)" ]; then
         nft 'add set inet fw4 openclash_google_dns_ipv6s { type ipv6_addr; flags interval; auto-merge; }'
         nft 'add element inet fw4 openclash_google_dns_ipv6s { 2001:4860:4860::8888, 2001:4860:4860::8844, 2001:4860:4860::6464, 2001:4860:4860::64 }'
         nft insert rule inet fw4 dstnat position 0 ip6 saddr @lan_block_google_dns_ipv6s ip6 daddr @openclash_google_dns_ipv6s counter accept comment \"OpenClash Google DNS Block\"
         nft insert rule inet fw4 dstnat position 0 ether saddr @lan_block_google_dns_macs ip6 daddr @openclash_google_dns_ipv6s counter accept comment \"OpenClash Google DNS Block\"
         nft insert rule inet fw4 forward position 0 ip6 saddr @lan_block_google_dns_ipv6s ip6 daddr @openclash_google_dns_ipv6s counter reject comment \"OpenClash Google DNS Block\"
         nft insert rule inet fw4 forward position 0 ether saddr @lan_block_google_dns_macs ip6 daddr @openclash_google_dns_ipv6s counter reject comment \"OpenClash Google DNS Block\"
      fi

      #intranet allowed
      if [ "$intranet_allowed" -eq 1 ]; then
         wan6_ints=$(nft list chain inet fw4 input |grep -e "jump input_wan" 2>/dev/null |awk '{for (i=1;i<=NF;i++){if ($i ~ /iifname/ && $(i+1) != "{") {print $(i+1)} if ($i ~ /iifname/ && $(i+1) == "{"){for (j=i+1;j<=NF;j++){if ($j~ /}/) {out="";for (k=i+1;k<=j;k++){out=out" "$k};print out}}}}}' 2>/dev/null |sed 's/"//g'|sed 's/{//g'|sed 's/}//g'|sed 's/,//g')
         if [ -n "$wan6_ints" ]; then
            nft 'add chain inet fw4 openclash_wan6_input'
            nft 'flush chain inet fw4 openclash_wan6_input'
            for wan6_int in $wan6_ints; do
               #nft delete rule inet fw4 input $(nft -a list chain inet fw4 input |grep "@localnetwork6" |awk -F '# ' '{print$2}')
               nft insert rule inet fw4 input position 0 iifname "$wan6_int" ip6 saddr != @localnetwork6 counter jump openclash_wan6_input
            done
            nft add rule inet fw4 openclash_wan6_input udp dport {$proxy_port,$tproxy_port,$cn_port,$http_port,$socks_port,$mixed_port,$dns_port} counter reject
            nft add rule inet fw4 openclash_wan6_input tcp dport {$proxy_port,$tproxy_port,$cn_port,$http_port,$socks_port,$mixed_port,$dns_port} counter reject
         else
            LOG_OUT "Warning: Can't Settting Only Intranet Allowed Function, Get IPv6 WAN Interfaces error, Please Verify The Firewall's WAN Zone Name is wan, Ignore This IF The Device Does not Have a WAN Interfaces..."
         fi
      fi
   fi
fi 2>/dev/null

#IPTABLES
if [ -z "$FW4" ]; then
   #lan_google_dns_ac
   if [ -n "$(uci -q get openclash.config.lan_block_google_dns_ips)" ]; then
      ipset create lan_block_google_dns_ips hash:net
      ipset create lan_block_google_dns_ipv6s hash:net family inet6
      config_load "openclash"
      config_list_foreach "config" "lan_block_google_dns_ips" ac_add "lan_block_google_dns_ips" "lan_block_google_dns_ipv6s"
   fi
   if [ -n "$(uci -q get openclash.config.lan_block_google_dns_macs)" ]; then
      ipset create lan_block_google_dns_macs hash:mac
      config_load "openclash"
      config_list_foreach "config" "lan_block_google_dns_macs" ac_add "lan_block_google_dns_macs"
   fi

   #lan_ac
   if [ "$lan_ac_mode" = "0" ]; then
      if [ -n "$(uci -q get openclash.config.lan_ac_black_ips)" ]; then
         ipset create lan_ac_black_ips hash:net
         ipset create lan_ac_black_ipv6s hash:net family inet6
         config_load "openclash"
         config_list_foreach "config" "lan_ac_black_ips" ac_add "lan_ac_black_ips" "lan_ac_black_ipv6s"
      fi
      if [ -n "$(uci -q get openclash.config.lan_ac_black_macs)" ]; then
         ipset create lan_ac_black_macs hash:mac
         config_load "openclash"
         config_list_foreach "config" "lan_ac_black_macs" ac_add "lan_ac_black_macs"
      fi
   elif [ "$lan_ac_mode" = "1" ]; then
      if [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ]; then
         ipset create lan_ac_white_ips hash:net
         ipset create lan_ac_white_ipv6s hash:net family inet6
         config_load "openclash"
         config_list_foreach "config" "lan_ac_white_ips" ac_add "lan_ac_white_ips" "lan_ac_white_ipv6s"
      fi
      if [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
         ipset create lan_ac_white_macs hash:mac
         config_load "openclash"
         config_list_foreach "config" "lan_ac_white_macs" ac_add "lan_ac_white_macs"
      fi
   fi

   #wan ac
   if [ -n "$(uci -q get openclash.config.wan_ac_black_ips)" ]; then
      ipset create wan_ac_black_ips hash:net
      ipset create wan_ac_black_ipv6s hash:net family inet6
      config_load "openclash"
      config_list_foreach "config" "wan_ac_black_ips" ac_add "wan_ac_black_ips" "wan_ac_black_ipv6s"
   fi

   #lan port ac
   if [ -n "$(uci -q get openclash.config.lan_ac_black_ports)" ]; then
      ipset create lan_ac_black_ports bitmap:port range 0-65535
      config_load "openclash"
      config_list_foreach "config" "lan_ac_black_ports" ac_add "lan_ac_black_ports"
   fi

   #local
   ipset create localnetwork hash:net
   if [ -f "/etc/openclash/custom/openclash_custom_localnetwork_ipv4.list" ]; then
      for line in `cat "/etc/openclash/custom/openclash_custom_localnetwork_ipv4.list"`
      do
         ipset add localnetwork "$line"
      done
   else
      ipset add localnetwork 0.0.0.0/8
      ipset add localnetwork 127.0.0.0/8
      ipset add localnetwork 10.0.0.0/8
      ipset add localnetwork 169.254.0.0/16
      ipset add localnetwork 192.168.0.0/16
      ipset add localnetwork 224.0.0.0/4
      ipset add localnetwork 240.0.0.0/4
      ipset add localnetwork 172.16.0.0/12
      ipset add localnetwork 100.64.0.0/10
   fi

   if [ -n "$wan_ip4s" ]; then
      for wan_ip4 in $wan_ip4s; do
         ipset add localnetwork "$wan_ip4"
      done
   fi

   #common ports
   if [ -n "$common_ports" ] && [ "$common_ports" != "0" ]; then
      ipset create common_ports bitmap:port range 0-65535
      for i in $common_port; do
         ipset add common_ports $i
      done
   fi

   #bypass gateway compatible
   if [ "$bypass_gateway_compatible" -eq 1 ]; then
      iptables -t nat -N openclash_post
      iptables -t nat -F openclash_post
      iptables -t nat -A openclash_post -m set --match-set localnetwork src -m set --match-set lan_ac_black_ports src -j RETURN >/dev/null 2>&1
      iptables -t nat -A openclash_post -m mark --mark "$PROXY_FWMARK" -j ACCEPT
      iptables -t nat -A openclash_post -m set --match-set localnetwork dst -j RETURN
      iptables -t nat -A openclash_post -m addrtype ! --src-type LOCAL -m owner ! --uid-owner 65534 -j MASQUERADE
      iptables -t nat -A POSTROUTING -m comment --comment "OpenClash Bypass Gateway Compatible" -j openclash_post
   fi

   #intranet allowed
   if [ "$intranet_allowed" -eq 1 ]; then
      wan_ints=$(iptables-save -t filter |grep -e "-j zone_wan_input" 2>/dev/null |awk '{for (i=1;i<=NF;i++) {if ($i ~ /-i/) {print $(i+1)}}}' 2>/dev/null)
      if [ -n "$wan_ints" ]; then
         iptables -t filter -N openclash_wan_input
         iptables -t filter -F openclash_wan_input
         for wan_int in $wan_ints; do
            iptables -t filter -I INPUT -i "$wan_int" -m set ! --match-set localnetwork src -j openclash_wan_input
         done
         iptables -t filter -A openclash_wan_input -p udp -m multiport --dport "$proxy_port,$tproxy_port,$cn_port,$http_port,$socks_port,$mixed_port,$dns_port" -j REJECT >/dev/null 2>&1
         iptables -t filter -A openclash_wan_input -p tcp -m multiport --dport "$proxy_port,$tproxy_port,$cn_port,$http_port,$socks_port,$mixed_port,$dns_port" -j REJECT >/dev/null 2>&1
      else
         LOG_OUT "Warning: Can't Settting Only Intranet Allowed Function, Get IPv4 WAN Interfaces error, Please Verify The Firewall's WAN Zone Name is wan, Ignore This IF The Device Does not Have a WAN Interfaces..."
      fi
   fi

   if [ "$china_ip_route" = "1" ] || [ "$disable_udp_quic" = "1" ]; then
      ipset -! flush china_ip_route
      ipset -! restore </etc/openclash/china_ip_route.ipset

      if [ "$enable_redirect_dns" != "2" ]; then
         mkdir -p ${DNSMASQ_CONF_DIR}
         echo "create china_ip_route_pass hash:net family inet hashsize 1024 maxelem 1000000" >/tmp/openclash_china_ip_route_pass.list
         awk '!/^$/&&!/^#/&&/(^([1-9]|1[0-9]|1[1-9]{2}|2[0-4][0-9]|25[0-5])\.)(([0-9]{1,2}|1[1-9]{2}|2[0-4][0-9]|25[0-5])\.){2}([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-5][0-9]|25[0-4])((\/[0-9][0-9])?)$/{printf("add china_ip_route_pass %s'" "'\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute_pass.list >>/tmp/openclash_china_ip_route_pass.list 2>/dev/null
         awk '!/^$/&&!/^#/&&!/(^([1-9]|1[0-9]|1[1-9]{2}|2[0-4][0-9]|25[0-5])\.)(([0-9]{1,2}|1[1-9]{2}|2[0-4][0-9]|25[0-5])\.){2}([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-5][0-9]|25[0-4])((\/[0-9][0-9])?)$/{printf("ipset=/%s/china_ip_route_pass'" "'\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute_pass.list >>${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute_pass.conf 2>/dev/null
         ipset -! flush china_ip_route_pass
         ipset -! restore </tmp/openclash_china_ip_route_pass.list
         rm -rf /tmp/openclash_china_ip_route_pass.list

         if [ "$en_mode" = "fake-ip" ] && [ "$china_ip_route" = "1" ]; then
            cat "/etc/openclash/accelerated-domains.china.conf" |awk -v dns="${custom_china_domain_dns_server}" -F '/' '!/^$/&&!/^#/{print $1"/"$2"/"dns}' >${DNSMASQ_CONF_DIR}/dnsmasq_accelerated-domains.china.conf
            for i in `awk '!/^$/&&!/^#/&&!/(^([1-9]|1[0-9]|1[1-9]{2}|2[0-4][0-9]|25[0-5])\.)(([0-9]{1,2}|1[1-9]{2}|2[0-4][0-9]|25[0-5])\.){2}([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-5][0-9]|25[0-4])((\/[0-9][0-9])?)$/{printf("%s\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute_pass.list`
            do
               sed -i "/server=\/${i}\//d" ${DNSMASQ_CONF_DIR}/dnsmasq_accelerated-domains.china.conf
            done
         fi
      fi
   fi

   DNSPORT=$(uci -q get dhcp.@dnsmasq[0].port)
   if [ -z "$DNSPORT" ]; then
      DNSPORT=$(netstat -nlp |grep -E '127.0.0.1:.*dnsmasq' |awk -F '127.0.0.1:' '{print $2}' |awk '{print $1}' |head -1 || echo 53)
   fi

   if [ "$enable_redirect_dns" -eq 1 ]; then
      if [ -z "$(iptables -t nat -nL PREROUTING --line-number |grep 'OpenClash DNS Hijack')" ]; then
         if [ "$lan_ac_mode" != "1" ]; then
            ACBLACKDNSFILTER=""
            if [ "$lan_ac_mode" = "0" ]; then
               if [ -n "$(uci -q get openclash.config.lan_ac_black_ips)" ]; then
                  ACBLACKDNSFILTER="-m set ! --match-set lan_ac_black_ips src"
               fi
               if [ -n "$(uci -q get openclash.config.lan_ac_black_macs)" ]; then
                  ACBLACKDNSFILTER="$ACBLACKDNSFILTER -m set ! --match-set lan_ac_black_macs src"
               fi
            fi
            iptables -t nat -I PREROUTING -p udp --dport 53 ${ACBLACKDNSFILTER} -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
            iptables -t nat -I PREROUTING -p tcp --dport 53 ${ACBLACKDNSFILTER} -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
         else
            iptables -t nat -I PREROUTING -p udp --dport 53 -m set --match-set lan_ac_white_ips src -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
            iptables -t nat -I PREROUTING -p tcp --dport 53 -m set --match-set lan_ac_white_ips src -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
            iptables -t nat -I PREROUTING -p udp --dport 53 -m set --match-set lan_ac_white_macs src -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
            iptables -t nat -I PREROUTING -p tcp --dport 53 -m set --match-set lan_ac_white_macs src -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
         fi
      fi
   elif [ "$enable_redirect_dns" -eq 2 ]; then
      iptables -t nat -N openclash_dns_redirect
      iptables -t nat -F openclash_dns_redirect
      if [ "$lan_ac_mode" != "1" ]; then
         ACBLACKDNSFILTER=""
         if [ "$lan_ac_mode" = "0" ]; then
            if [ -n "$(uci -q get openclash.config.lan_ac_black_ips)" ]; then
               ACBLACKDNSFILTER="-m set ! --match-set lan_ac_black_ips src"
            fi
            if [ -n "$(uci -q get openclash.config.lan_ac_black_macs)" ]; then
               ACBLACKDNSFILTER="$ACBLACKDNSFILTER -m set ! --match-set lan_ac_black_macs src"
            fi
         fi
         iptables -t nat -A openclash_dns_redirect -p udp --dport 53 ${ACBLACKDNSFILTER} -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
         iptables -t nat -A openclash_dns_redirect -p tcp --dport 53 ${ACBLACKDNSFILTER} -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
      else
         iptables -t nat -A openclash_dns_redirect -p udp --dport 53 -m set --match-set lan_ac_white_ips src -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
         iptables -t nat -A openclash_dns_redirect -p tcp --dport 53 -m set --match-set lan_ac_white_ips src -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
         iptables -t nat -A openclash_dns_redirect -p udp --dport 53 -m set --match-set lan_ac_white_macs src -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
         iptables -t nat -A openclash_dns_redirect -p tcp --dport 53 -m set --match-set lan_ac_white_macs src -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
      fi
      iptables -t nat -I PREROUTING -p udp --dport 53 -j openclash_dns_redirect
      iptables -t nat -I PREROUTING -p tcp --dport 53 -j openclash_dns_redirect
      if [ "$router_self_proxy" = 1 ]; then
         iptables -t nat -I OUTPUT -p udp --dport 53 -d 127.0.0.1 -m owner ! --uid-owner 65534 -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
         iptables -t nat -I OUTPUT -p tcp --dport 53 -d 127.0.0.1 -m owner ! --uid-owner 65534 -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
      fi
   fi

   if [ "$en_mode" = "fake-ip" ] && [ "$china_ip_route" = "1" ] && [ "$enable_redirect_dns" != "2" ]; then
      LOG_OUT "Tip: Bypass the China IP May Cause the Dnsmasq Load For a Long Time After Restart in FAKE-IP Mode, Hijack the DNS to Core Untill the Dnsmasq Works Well..."
      iptables -t nat -I PREROUTING -p udp --dport 53 -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
      iptables -t nat -I PREROUTING -p tcp --dport 53 -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
      iptables -t nat -I OUTPUT -p udp --dport 53 -m owner ! --uid-owner 65534 -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
      iptables -t nat -I OUTPUT -p tcp --dport 53 -m owner ! --uid-owner 65534 -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
      iptables -t nat -I OUTPUT -p udp --dport 12353 -m owner ! --uid-owner 65534 -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
      iptables -t nat -I OUTPUT -p tcp --dport 12353 -m owner ! --uid-owner 65534 -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
   fi

   if [ -z "$en_mode_tun" ] || [ "$en_mode_tun" -eq 2 ]; then
      #tcp
      iptables -t nat -N openclash
      iptables -t nat -F openclash
      iptables -t nat -A openclash -m set --match-set localnetwork dst -j RETURN
      if [ -z "$en_mode_tun" ] && [ "$en_mode" = "fake-ip" ]; then
         iptables -t nat -A openclash -p tcp -d "$fakeip_range" -j REDIRECT --to-ports "$proxy_port"
      fi
      iptables -t nat -A openclash -m set --match-set localnetwork src -m set --match-set lan_ac_black_ports src -j RETURN >/dev/null 2>&1
      iptables -t nat -A openclash -m set --match-set wan_ac_black_ips dst -j RETURN >/dev/null 2>&1
      iptables -t nat -A openclash -m set --match-set lan_ac_black_ips src -j RETURN >/dev/null 2>&1
      iptables -t nat -A openclash -m set --match-set lan_ac_black_macs src -j RETURN >/dev/null 2>&1
      if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
         iptables -t nat -A openclash -m set ! --match-set lan_ac_white_ips src -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
      else
         iptables -t nat -A openclash -m set ! --match-set lan_ac_white_ips src -j RETURN >/dev/null 2>&1
         iptables -t nat -A openclash -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
      fi
      if [ "$en_mode" = "redir-host" ]; then
         iptables -t nat -A openclash -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
      fi
      if [ "$china_ip_route" = "1" ]; then
         if [ "$enable_redirect_dns" != "2" ]; then
            iptables -t nat -A openclash -m set --match-set china_ip_route dst -m set ! --match-set china_ip_route_pass dst -j RETURN >/dev/null 2>&1
         else
            iptables -t nat -A openclash -m set --match-set china_ip_route dst -j RETURN >/dev/null 2>&1
         fi
      fi
      iptables -t nat -A openclash -p tcp -j REDIRECT --to-ports "$proxy_port"
      iptables -t nat -A PREROUTING -p tcp -j openclash

      if [ -z "$en_mode_tun" ]; then
         #Google dns
         iptables -t nat -I PREROUTING -m comment --comment "OpenClash Google DNS Hijack" -p tcp -d 8.8.8.8 --dport 53 -j REDIRECT --to-ports "$proxy_port"
         iptables -t nat -I PREROUTING -m comment --comment "OpenClash Google DNS Hijack" -p tcp -d 8.8.4.4 --dport 53 -j REDIRECT --to-ports "$proxy_port"
         #udp
         if [ "$enable_udp_proxy" -eq 1 ]; then
            modprobe xt_TPROXY >/dev/null 2>&1
            ip rule add fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE"
            ip route add local 0.0.0.0/0 dev lo table "$PROXY_ROUTE_TABLE"
            iptables -t mangle -N openclash
            iptables -t mangle -F openclash
            iptables -t mangle -N openclash_upnp
            iptables -t mangle -F openclash_upnp
            upnp_exclude
            #prevent tproxy loop
            iptables -t mangle -A openclash -i lo -j RETURN
            iptables -t mangle -A openclash -m set --match-set localnetwork dst -j RETURN
            iptables -t mangle -A openclash -p udp --dport 53 -j RETURN >/dev/null 2>&1
            if [ "$en_mode" = "fake-ip" ]; then
               iptables -t mangle -A openclash -p udp -d "$fakeip_range" -j TPROXY --on-port "$tproxy_port" --tproxy-mark "$PROXY_FWMARK"
            fi
            iptables -t mangle -A openclash -m set --match-set localnetwork src -m set --match-set lan_ac_black_ports src -j RETURN >/dev/null 2>&1
            iptables -t mangle -A openclash -m set --match-set wan_ac_black_ips dst -j RETURN >/dev/null 2>&1
            iptables -t mangle -A openclash -m set --match-set lan_ac_black_macs src -j RETURN >/dev/null 2>&1
            iptables -t mangle -A openclash -m set --match-set lan_ac_black_ips src -j RETURN >/dev/null 2>&1
            if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
               iptables -t mangle -A openclash -m set ! --match-set lan_ac_white_ips src -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
            else
               iptables -t mangle -A openclash -m set ! --match-set lan_ac_white_ips src -j RETURN >/dev/null 2>&1
               iptables -t mangle -A openclash -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
            fi
            if [ "$en_mode" = "redir-host" ]; then
               iptables -t mangle -A openclash -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
            fi
            if [ "$china_ip_route" = "1" ]; then
               if [ "$enable_redirect_dns" != "2" ]; then
                  iptables -t mangle -A openclash -m set --match-set china_ip_route dst -m set ! --match-set china_ip_route_pass dst -j RETURN >/dev/null 2>&1
               else
                  iptables -t mangle -A openclash -m set --match-set china_ip_route dst -j RETURN >/dev/null 2>&1
               fi
            fi
            iptables -t mangle -A openclash -p udp -j openclash_upnp >/dev/null 2>&1
            iptables -t mangle -A openclash -p udp -j TPROXY --on-port "$tproxy_port" --tproxy-mark "$PROXY_FWMARK"
            iptables -t mangle -A PREROUTING -p udp -j openclash

         elif [ "$en_mode" = "fake-ip" ]; then
            modprobe xt_TPROXY >/dev/null 2>&1
            ip rule add fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE"
            ip route add local 0.0.0.0/0 dev lo table "$PROXY_ROUTE_TABLE"
            iptables -t mangle -N openclash
            iptables -t mangle -F openclash
            #prevent tproxy loop
            iptables -t mangle -A openclash -i lo -j RETURN
            iptables -t mangle -A openclash -p udp -d "$fakeip_range" -j TPROXY --on-port "$tproxy_port" --tproxy-mark "$PROXY_FWMARK"
            iptables -t mangle -A PREROUTING -p udp -j openclash
         fi

         if [ "$router_self_proxy" = "1" ] || ([ "$enable_redirect_dns" != "2" ] && [ "$en_mode" = "fake-ip" ]); then
            iptables -t mangle -N openclash_output
            iptables -t mangle -F openclash_output
            iptables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -p udp -d "$fakeip_range" -j MARK --set-mark "$PROXY_FWMARK"
            iptables -t mangle -A OUTPUT -p udp -j openclash_output
         fi

         #quic
         if [ "$disable_udp_quic" -eq 1 ]; then
            iptables -I INPUT -p udp --dport 443 -m comment --comment "OpenClash QUIC REJECT" -m set ! --match-set china_ip_route dst -j REJECT >/dev/null 2>&1
         fi
      fi

      if [ "$router_self_proxy" = "1" ] || ([ "$enable_redirect_dns" != "2" ] && [ "$en_mode" = "fake-ip" ]); then
         iptables -t nat -N openclash_output
         iptables -t nat -F openclash_output
         if [ "$en_mode" = "fake-ip" ] && [ "$en_mode_tun" != "1" ]; then
            iptables -t nat -A openclash_output -m owner ! --uid-owner 65534 -p tcp -d "$fakeip_range" -j REDIRECT --to-ports "$proxy_port"
         fi
         if [ "$router_self_proxy" = "1" ]; then
            iptables -t nat -A openclash_output -m set --match-set localnetwork dst -j RETURN
            iptables -t nat -A openclash_output -m set --match-set localnetwork src -m set --match-set lan_ac_black_ports src -j RETURN >/dev/null 2>&1
            iptables -t nat -A openclash_output -m owner ! --uid-owner 65534 -m set --match-set wan_ac_black_ips dst -j RETURN >/dev/null 2>&1
            if [ "$en_mode" = "redir-host" ]; then
               iptables -t nat -A openclash_output -m owner ! --uid-owner 65534 -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
            fi
            if [ "$china_ip_route" = "1" ]; then
               if [ "$enable_redirect_dns" != "2" ]; then
                  iptables -t nat -A openclash_output -m owner ! --uid-owner 65534 -m set --match-set china_ip_route dst -m set ! --match-set china_ip_route_pass dst -j RETURN >/dev/null 2>&1
               else
                  iptables -t nat -A openclash_output -m owner ! --uid-owner 65534 -m set --match-set china_ip_route dst -j RETURN >/dev/null 2>&1
               fi
            fi
            iptables -t nat -A openclash_output -m owner ! --uid-owner 65534 -p tcp -j REDIRECT --to-ports "$proxy_port"
         fi
         iptables -t nat -A OUTPUT -j openclash_output >/dev/null 2>&1
      fi
   fi

   if [ -n "$en_mode_tun" ]; then
      #TUN模式
      #启动TUN
      set_tun_tap
      #设置防火墙
      if [ "$router_self_proxy" = "1" ] || ([ "$enable_redirect_dns" != "2" ] && [ "$en_mode" = "fake-ip" ]); then
         if [ "$en_mode" = "fake-ip" ]; then
            iptables -t mangle -N openclash_output
            iptables -t mangle -F openclash_output
            iptables -t mangle -A openclash_output -m set --match-set localnetwork dst -j RETURN
            iptables -t mangle -A openclash_output -m set --match-set localnetwork src -m set --match-set lan_ac_black_ports src -j RETURN >/dev/null 2>&1
            if [ "$en_mode_tun" -eq 1 ]; then
               iptables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -d "$fakeip_range" -j MARK --set-mark "$PROXY_FWMARK"
               if [ "$router_self_proxy" = "1" ]; then
                  iptables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -m set --match-set wan_ac_black_ips dst -j RETURN >/dev/null 2>&1
                  if [ "$china_ip_route" = "1" ]; then
                     if [ "$enable_redirect_dns" != "2" ]; then
                        iptables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -m set --match-set china_ip_route dst -m set ! --match-set china_ip_route_pass dst -j RETURN >/dev/null 2>&1
                     else
                        iptables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -m set --match-set china_ip_route dst -j RETURN >/dev/null 2>&1
                     fi
                  fi
                  iptables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -p tcp -j MARK --set-mark "$PROXY_FWMARK"
               fi
            else
               iptables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -p udp -d "$fakeip_range" -j MARK --set-mark "$PROXY_FWMARK"
            fi
            iptables -t mangle -A OUTPUT -j openclash_output
         elif [ "$en_mode" = "redir-host" ] && [ "$en_mode_tun" -eq 1 ]; then
            iptables -t mangle -N openclash_output
            iptables -t mangle -F openclash_output
            iptables -t mangle -A openclash_output -m set --match-set localnetwork dst -j RETURN
            iptables -t mangle -A openclash_output -m set --match-set localnetwork src -m set --match-set lan_ac_black_ports src -j RETURN >/dev/null 2>&1
            iptables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -m set --match-set wan_ac_black_ips dst -j RETURN >/dev/null 2>&1
            iptables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
            if [ "$china_ip_route" = "1" ]; then
               if [ "$enable_redirect_dns" != "2" ]; then
                  iptables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -m set --match-set china_ip_route dst -m set ! --match-set china_ip_route_pass dst -j RETURN >/dev/null 2>&1
               else
                  iptables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -m set --match-set china_ip_route dst -j RETURN >/dev/null 2>&1
               fi
            fi
            iptables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -p tcp -j MARK --set-mark "$PROXY_FWMARK"
            iptables -t mangle -A OUTPUT -j openclash_output
         fi
      fi

      iptables -t mangle -N openclash
      iptables -t mangle -F openclash
      iptables -t mangle -N openclash_dns_hijack
      iptables -t mangle -F openclash_dns_hijack
      iptables -t mangle -N openclash_upnp
      iptables -t mangle -F openclash_upnp
      upnp_exclude
      #其他流量
      iptables -t mangle -A openclash -i utun -j RETURN
      iptables -t mangle -A openclash -m set --match-set localnetwork dst -j RETURN
      iptables -t mangle -A openclash -m set --match-set localnetwork src -m set --match-set lan_ac_black_ports src -j RETURN >/dev/null 2>&1
      iptables -t mangle -A openclash -m set --match-set wan_ac_black_ips dst -j RETURN >/dev/null 2>&1
      iptables -t mangle -A openclash -m set --match-set lan_ac_black_ips src -j RETURN >/dev/null 2>&1
      iptables -t mangle -A openclash -m set --match-set lan_ac_black_macs src -j RETURN >/dev/null 2>&1
      if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
         iptables -t mangle -A openclash -m set ! --match-set lan_ac_white_ips src -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
      else
         iptables -t mangle -A openclash -m set ! --match-set lan_ac_white_ips src -j RETURN >/dev/null 2>&1
         iptables -t mangle -A openclash -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
      fi

      if [ "$en_mode" = "redir-host" ]; then
         iptables -t mangle -A openclash -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
      fi
      if [ "$china_ip_route" = "1" ]; then
         if [ "$enable_redirect_dns" != "2" ]; then
            iptables -t mangle -A openclash -m set --match-set china_ip_route dst -m set ! --match-set china_ip_route_pass dst -j RETURN >/dev/null 2>&1
         else
            iptables -t mangle -A openclash -m set --match-set china_ip_route dst -j RETURN >/dev/null 2>&1
         fi
      fi

      iptables -t mangle -A openclash -p udp -j openclash_upnp >/dev/null 2>&1

      iptables -t mangle -A openclash -j MARK --set-mark "$PROXY_FWMARK"

      if [ "$en_mode_tun" -eq 1 ]; then
         iptables -t mangle -I PREROUTING -j openclash
      else
         if [ "$enable_redirect_dns" -eq 1 ]; then
            iptables -t mangle -I PREROUTING -p tcp --dport 53 -j openclash_dns_hijack
            iptables -t mangle -A openclash_dns_hijack -m set --match-set lan_ac_black_ips src -j RETURN >/dev/null 2>&1
            iptables -t mangle -A openclash_dns_hijack -m set --match-set lan_ac_black_macs src -j RETURN >/dev/null 2>&1
            if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
               iptables -t mangle -A openclash_dns_hijack -m set ! --match-set lan_ac_white_ips src -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
            else
               iptables -t mangle -A openclash_dns_hijack -m set ! --match-set lan_ac_white_ips src -j RETURN >/dev/null 2>&1
               iptables -t mangle -A openclash_dns_hijack -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
            fi
            iptables -t mangle -A openclash_dns_hijack -m comment --comment "OpenClash TCP DNS Hijack" -p tcp --dport 53 -j MARK --set-mark "$PROXY_FWMARK"
         fi
         iptables -t mangle -I PREROUTING -p udp -j openclash
      fi

      if [ "$enable_redirect_dns" -eq 2 ]; then
         local position=$(iptables -nvL openclash_dns_redirect -t nat |grep "DNS" |grep -v "REDIRECT" |wc -l)
         let position++
         iptables -t nat -I openclash_dns_redirect "$position" -m comment --comment "OpenClash TCP DNS Hijack" -p tcp --dport 53 -j ACCEPT
      elif [ "$enable_redirect_dns" -eq 1 ]; then
         iptables -t nat -I PREROUTING -m comment --comment "OpenClash TCP DNS Hijack" -p tcp --dport 53 -j ACCEPT
      fi

      #TUN FORWORD
      iptables -I FORWARD -m comment --comment "OpenClash TUN Forward" -o utun -j ACCEPT

      #quic
      if [ "$disable_udp_quic" -eq 1 ]; then
         iptables -I FORWARD -p udp --dport 443 -o utun -m comment --comment "OpenClash QUIC REJECT" -m set ! --match-set china_ip_route dst -j REJECT >/dev/null 2>&1
      fi
   fi

   #google_dns_block
   if [ -n "$(uci -q get openclash.config.lan_block_google_dns_ips)" ] || [ -n "$(uci -q get openclash.config.lan_block_google_dns_macs)" ]; then
      ipset create openclash_google_dns_ips hash:net
      ipset add openclash_google_dns_ips 8.8.8.8
      ipset add openclash_google_dns_ips 8.8.4.4

      if [ -z "$en_mode_tun" ] || [ "$en_mode_tun" -eq 2 ]; then
         iptables -t nat -I PREROUTING -m comment --comment "OpenClash Google DNS Block" -m set --match-set lan_block_google_dns_ips src -m set --match-set openclash_google_dns_ips dst -j ACCEPT >/dev/null 2>&1
         iptables -t nat -I PREROUTING -m comment --comment "OpenClash Google DNS Block" -m set --match-set lan_block_google_dns_macs src -m set --match-set openclash_google_dns_ips dst -j ACCEPT >/dev/null 2>&1
      fi
      iptables -t filter -I FORWARD -m set --match-set lan_block_google_dns_ips src -m set --match-set openclash_google_dns_ips dst -j REJECT >/dev/null 2>&1
      iptables -t filter -I FORWARD -m set --match-set lan_block_google_dns_macs src -m set --match-set openclash_google_dns_ips dst -j REJECT >/dev/null 2>&1
   fi

   #ipv6
   if [ "$ipv6_enable" -eq 1 ] && [ -n "$(ip6tables -t mangle -L 2>&1 | grep -o 'Chain')" ]; then
      if [ -z "$(ip6tables -t nat -nL PREROUTING --line-number |grep 'DNS Hijack')" ]; then
         if [ "$enable_redirect_dns" -eq 1 ]; then
            if [ "$lan_ac_mode" != "1" ]; then
               ACBLACKDNSFILTER=""
               if [ "$lan_ac_mode" = "0" ]; then
                  if [ -n "$(uci -q get openclash.config.lan_ac_black_ips)" ]; then
                     ACBLACKDNSFILTER="-m set ! --match-set lan_ac_black_ipv6s src"
                  fi
                  if [ -n "$(uci -q get openclash.config.lan_ac_black_macs)" ]; then
                     ACBLACKDNSFILTER="$ACBLACKDNSFILTER -m set ! --match-set lan_ac_black_macs src"
                  fi
               fi
               ip6tables -t nat -I PREROUTING -p udp --dport 53 ${ACBLACKDNSFILTER} -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
               ip6tables -t nat -I PREROUTING -p tcp --dport 53 ${ACBLACKDNSFILTER} -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
            else
               ip6tables -t nat -I PREROUTING -p udp --dport 53 -m set --match-set lan_ac_white_ipv6s src -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
               ip6tables -t nat -I PREROUTING -p tcp --dport 53 -m set --match-set lan_ac_white_ipv6s src -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
               ip6tables -t nat -I PREROUTING -p udp --dport 53 -m set --match-set lan_ac_white_macs src -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
               ip6tables -t nat -I PREROUTING -p tcp --dport 53 -m set --match-set lan_ac_white_macs src -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
            fi
         elif [ "$enable_redirect_dns" -eq 2 ]; then
            ip6tables -t nat -N openclash_dns_redirect
            ip6tables -t nat -F openclash_dns_redirect
            if [ "$lan_ac_mode" != "1" ]; then
               ACBLACKDNSFILTER=""
               if [ "$lan_ac_mode" = "0" ]; then
                  if [ -n "$(uci -q get openclash.config.lan_ac_black_ips)" ]; then
                     ACBLACKDNSFILTER="-m set ! --match-set lan_ac_black_ipv6s src"
                  fi
                  if [ -n "$(uci -q get openclash.config.lan_ac_black_macs)" ]; then
                     ACBLACKDNSFILTER="$ACBLACKDNSFILTER -m set ! --match-set lan_ac_black_macs src"
                  fi
               fi
               ip6tables -t nat -A openclash_dns_redirect -p udp --dport 53 ${ACBLACKDNSFILTER} -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
               ip6tables -t nat -A openclash_dns_redirect -p tcp --dport 53 ${ACBLACKDNSFILTER} -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
            else
               ip6tables -t nat -A openclash_dns_redirect -p udp --dport 53 -m set --match-set lan_ac_white_ipv6s src -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
               ip6tables -t nat -A openclash_dns_redirect -p tcp --dport 53 -m set --match-set lan_ac_white_ipv6s src -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
               ip6tables -t nat -A openclash_dns_redirect -p udp --dport 53 -m set --match-set lan_ac_white_macs src -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
               ip6tables -t nat -A openclash_dns_redirect -p tcp --dport 53 -m set --match-set lan_ac_white_macs src -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
            fi
            ip6tables -t nat -I PREROUTING -p udp --dport 53 -j openclash_dns_redirect
            ip6tables -t nat -I PREROUTING -p tcp --dport 53 -j openclash_dns_redirect
            if [ "$router_self_proxy" = 1 ]; then
               ip6tables -t nat -I OUTPUT -p udp --dport 53 -d ::/0 -m owner ! --uid-owner 65534 -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
               ip6tables -t nat -I OUTPUT -p tcp --dport 53 -d ::/0 -m owner ! --uid-owner 65534 -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
            fi
         fi
      fi
      if [ "$en_mode" = "fake-ip" ] && [ "$china_ip_route" = "1" ] && [ "$enable_redirect_dns" != "2" ]; then
         ip6tables -t nat -I PREROUTING -p udp --dport 53 -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
         ip6tables -t nat -I PREROUTING -p tcp --dport 53 -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
         ip6tables -t nat -I OUTPUT -p udp --dport 53 -m owner ! --uid-owner 65534 -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
         ip6tables -t nat -I OUTPUT -p tcp --dport 53 -m owner ! --uid-owner 65534 -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
         ip6tables -t nat -I OUTPUT -p udp --dport 12353 -m owner ! --uid-owner 65534 -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
         ip6tables -t nat -I OUTPUT -p tcp --dport 12353 -m owner ! --uid-owner 65534 -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
      fi

      if [ "$china_ip6_route" = "1" ] || [ "$disable_udp_quic" = "1" ]; then
         ipset -! flush china_ip6_route
         ipset -! restore </etc/openclash/china_ip6_route.ipset
         if [ "$enable_redirect_dns" != "2" ]; then
            mkdir -p ${DNSMASQ_CONF_DIR}
            echo "create china_ip6_route_pass hash:net family inet6 hashsize 1024 maxelem 1000000" >/tmp/openclash_china_ip6_route_pass.list
            awk '!/^$/&&!/^#/&&!/^(\*?\.?)*[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})*$/{printf("add china_ip6_route_pass %s'" "'\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute6_pass.list >>/tmp/openclash_china_ip6_route_pass.list
            awk '!/^$/&&!/^#/&&/^(\*?\.?)*[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})*$/{printf("ipset=/%s/china_ip_route_pass'" "'\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute6_pass.list >>${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf
            ipset -! flush china_ip6_route_pass
            ipset -! restore </tmp/openclash_china_ip6_route_pass.list
            rm -rf /tmp/openclash_china_ip6_route_pass.list

            #Prevent domain repeat
            for i in `grep -wf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute_pass.conf`
            do
               sed -i "s:${i}:${i},china_ip6_route_pass:g" ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute_pass.conf
               sed -i 's:'$i':EXCLUSIVE:;/EXCLUSIVE/d' ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf
            done
            sed -i "s/china_ip_route_pass/china_ip6_route_pass/g" ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf
         fi
      fi

      #local
      ipset create localnetwork6 hash:net family inet6
      if [ -f "/etc/openclash/custom/openclash_custom_localnetwork_ipv6.list" ]; then
         for line in `cat "/etc/openclash/custom/openclash_custom_localnetwork_ipv6.list"`
         do
            ipset add localnetwork6 "$line"
         done
      else
         ipset add localnetwork6 ::/128
         ipset add localnetwork6 ::1/128
         ipset add localnetwork6 ::ffff:0:0/96
         ipset add localnetwork6 ::ffff:0:0:0/96
         ipset add localnetwork6 64:ff9b::/96
         ipset add localnetwork6 100::/64
         ipset add localnetwork6 2001::/32
         ipset add localnetwork6 2001:20::/28
         ipset add localnetwork6 2001:db8::/32
         ipset add localnetwork6 2002::/16
         ipset add localnetwork6 fc00::/7
         ipset add localnetwork6 fe80::/10
         ipset add localnetwork6 ff00::/8
      fi

      if [ -n "$wan_ip6s" ]; then
         for wan_ip6 in $wan_ip6s; do
            ipset add localnetwork6 "$wan_ip6"
         done
      fi

      #Google dns
      ip6tables -t nat -I PREROUTING -m comment --comment "OpenClash Google DNS Hijack" -p tcp -d 2001:4860:4860::8888 --dport 53 -j ACCEPT
      ip6tables -t nat -I PREROUTING -m comment --comment "OpenClash Google DNS Hijack" -p tcp -d 2001:4860:4860::8844 --dport 53 -j ACCEPT

      if [ "$ipv6_mode" -eq 1 ]; then
         #tcp
         ip6tables -t nat -N openclash
         ip6tables -t nat -F openclash
         ip6tables -t nat -A openclash -m set --match-set localnetwork6 dst -j RETURN
         ip6tables -t nat -A openclash -m set --match-set localnetwork6 src -m set --match-set lan_ac_black_ports src -j RETURN >/dev/null 2>&1
         ip6tables -t nat -A openclash -m set --match-set wan_ac_black_ipv6s dst -j RETURN >/dev/null 2>&1
         ip6tables -t nat -A openclash -m set --match-set lan_ac_black_ipv6s src -j RETURN >/dev/null 2>&1
         ip6tables -t nat -A openclash -m set --match-set lan_ac_black_macs src -j RETURN >/dev/null 2>&1
         if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
            ip6tables -t nat -A openclash -m set ! --match-set lan_ac_white_ipv6s src -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
         else
            ip6tables -t nat -A openclash -m set ! --match-set lan_ac_white_ipv6s src -j RETURN >/dev/null 2>&1
            ip6tables -t nat -A openclash -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
         fi
         if [ "$en_mode" = "redir-host" ]; then
            ip6tables -t nat -A openclash -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
         fi
         if [ "$china_ip6_route" = "1" ]; then
            if [ "$enable_redirect_dns" != "2" ]; then
               ip6tables -t nat -A openclash -m set --match-set china_ip6_route dst -m set ! --match-set china_ip6_route_pass dst -j RETURN >/dev/null 2>&1
            else
               ip6tables -t nat -A openclash -m set --match-set china_ip6_route dst -j RETURN >/dev/null 2>&1
            fi
         fi
         ip6tables -t nat -A openclash -p tcp -j REDIRECT --to-ports "$proxy_port"
         ip6tables -t nat -A PREROUTING -p tcp -j openclash
      fi
      #tproxy not support output chain
      if [ "$ipv6_mode" -eq 0 ] || [ "$ipv6_mode" -eq 1 ]; then
         if [ "$router_self_proxy" = "1" ]; then
            ip6tables -t nat -N openclash_output
            ip6tables -t nat -F openclash_output
            ip6tables -t nat -A openclash_output -m set --match-set localnetwork6 dst -j RETURN
            ip6tables -t nat -A openclash_output -m set --match-set localnetwork6 src -m set --match-set lan_ac_black_ports src -j RETURN >/dev/null 2>&1
            ip6tables -t nat -A openclash_output -m owner ! --uid-owner 65534 -m set --match-set wan_ac_black_ipv6s dst -j RETURN >/dev/null 2>&1
            if [ "$en_mode" = "redir-host" ]; then
               ip6tables -t nat -A openclash_output -m owner ! --uid-owner 65534 -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
            fi
            if [ "$china_ip6_route" = "1" ]; then
               if [ "$enable_redirect_dns" != "2" ]; then
                  ip6tables -t nat -A openclash_output -m owner ! --uid-owner 65534 -m set --match-set china_ip6_route dst -m set ! --match-set china_ip6_route_pass dst -j RETURN >/dev/null 2>&1
               else
                  ip6tables -t nat -A openclash_output -m owner ! --uid-owner 65534 -m set --match-set china_ip6_route dst -j RETURN >/dev/null 2>&1
               fi
            fi
            ip6tables -t nat -A openclash_output -m owner ! --uid-owner 65534 -p tcp -j REDIRECT --to-ports "$proxy_port"
            ip6tables -t nat -A OUTPUT -j openclash_output >/dev/null 2>&1
         fi
      fi

      if [ "$enable_v6_udp_proxy" -eq 1 ] || [ "$ipv6_mode" -eq 0 ] || [ "$ipv6_mode" -eq 2 ]; then
         ip6tables -t mangle -N openclash
         ip6tables -t mangle -F openclash
         #prevent tproxy loop
         ip6tables -t mangle -A openclash -i lo -j RETURN
         ip6tables -t mangle -A openclash -m set --match-set localnetwork6 dst -j RETURN
         ip6tables -t mangle -A openclash -p udp --dport 53 -j RETURN
         ip6tables -t mangle -A openclash -m set --match-set localnetwork6 src -m set --match-set lan_ac_black_ports src -j RETURN >/dev/null 2>&1
         ip6tables -t mangle -A openclash -m set --match-set wan_ac_black_ipv6s dst -j RETURN >/dev/null 2>&1
         ip6tables -t mangle -A openclash -m set --match-set lan_ac_black_macs src -j RETURN >/dev/null 2>&1
         ip6tables -t mangle -A openclash -m set --match-set lan_ac_black_ipv6s src -j RETURN >/dev/null 2>&1
         if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
            ip6tables -t mangle -A openclash -m set ! --match-set lan_ac_white_ipv6s src -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
         else
            ip6tables -t mangle -A openclash -m set ! --match-set lan_ac_white_ipv6s src -j RETURN >/dev/null 2>&1
            ip6tables -t mangle -A openclash -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
         fi

         if [ "$en_mode" == "redir-host" ]; then
            ip6tables -t mangle -A openclash -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
         fi

         if [ "$china_ip6_route" = "1" ]; then
            if [ "$enable_redirect_dns" != "2" ]; then
               ip6tables -t mangle -A openclash -m set --match-set china_ip6_route dst -m set ! --match-set china_ip6_route_pass dst -j RETURN >/dev/null 2>&1
            else
               ip6tables -t mangle -A openclash -m set --match-set china_ip6_route dst -j RETURN >/dev/null 2>&1
            fi
         fi
      fi

      #TProxy & TUN
      if [ "$ipv6_mode" -ne 1 ]; then
         if [ "$ipv6_mode" -eq 0 ]; then
            ip6tables -t mangle -A openclash -p tcp -m comment --comment "OpenClash TCP Tproxy" -j TPROXY --on-port "$tproxy_port" --tproxy-mark "$PROXY_FWMARK"
         elif [ "$ipv6_mode" -eq 2 ]; then
            ip6tables -t mangle -A openclash -p tcp -j MARK --set-mark "$PROXY_FWMARK"
         fi

         if [ "$ipv6_mode" -eq 2 ]; then
            if [ "$router_self_proxy" = "1" ]; then
               ip6tables -t mangle -N openclash_output
               ip6tables -t mangle -F openclash_output
               ip6tables -t mangle -A openclash_output -m set --match-set localnetwork6 dst -j RETURN
               ip6tables -t mangle -A openclash_output -m set --match-set localnetwork6 src -m set --match-set lan_ac_black_ports src -j RETURN >/dev/null 2>&1
               ip6tables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -m set --match-set wan_ac_black_ipv6s dst -j RETURN >/dev/null 2>&1
               if [ "$en_mode" = "redir-host" ]; then
                  ip6tables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
               fi
               if [ "$china_ip6_route" = "1" ]; then
                  if [ "$enable_redirect_dns" != "2" ]; then
                     ip6tables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -m set --match-set china_ip6_route dst -m set ! --match-set china_ip6_route_pass dst -j RETURN >/dev/null 2>&1
                  else
                     ip6tables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -m set --match-set china_ip6_route dst -j RETURN >/dev/null 2>&1
                  fi
               fi
               ip6tables -t mangle -A openclash_output -p tcp -m owner ! --uid-owner 65534 -j MARK --set-xmark "$PROXY_FWMARK"
               ip6tables -t mangle -A OUTPUT -j openclash_output
            fi
         fi
      fi

      #udp
      if [ "$ipv6_mode" -eq 2 ]; then
         ip6tables -t mangle -A openclash -p udp -m comment --comment "OpenClash UDP TUN" -j MARK --set-xmark "$PROXY_FWMARK"
      else
         if [ "$enable_v6_udp_proxy" -eq 1 ]; then
            ip6tables -t mangle -A openclash -p udp -m comment --comment "OpenClash UDP Tproxy" -j TPROXY --on-port "$tproxy_port" --tproxy-mark "$PROXY_FWMARK"
         fi
      fi

      ip6tables -t mangle -A PREROUTING -j openclash

      #route
      if [ "$ipv6_mode" -ne 2 ]; then
         if [ "$enable_v6_udp_proxy" -eq 1 ] || [ "$ipv6_mode" -eq 0 ]; then
            modprobe xt_TPROXY >/dev/null 2>&1
            ip -6 rule add fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE"
            ip -6 route add local ::/0 dev lo table "$PROXY_ROUTE_TABLE"
         fi
      else
         set_tun_tap "v6"
      fi

      #quic
      if [ "$disable_udp_quic" -eq 1 ]; then
         ip6tables -I INPUT -p udp --dport 443 -m comment --comment "OpenClash QUIC REJECT" -m set ! --match-set china_ip6_route dst -j REJECT >/dev/null 2>&1
      fi

      #bypass gateway compatible
      if [ "$bypass_gateway_compatible" -eq 1 ]; then
         ip6tables -t nat -N openclash_post
         ip6tables -t nat -F openclash_post
         ip6tables -t nat -A openclash_post -m set --match-set localnetwork src -m set --match-set lan_ac_black_ports src -j RETURN >/dev/null 2>&1
         ip6tables -t nat -A openclash_post -m mark --mark "$PROXY_FWMARK" -j ACCEPT
         ip6tables -t nat -A openclash_post -m set --match-set localnetwork6 dst -j RETURN
         ip6tables -t nat -A openclash_post -m addrtype ! --src-type LOCAL -m owner ! --uid-owner 65534 -j MASQUERADE
         ip6tables -t nat -A POSTROUTING -m comment --comment "OpenClash Bypass Gateway Compatible" -j openclash_post
      fi

      #google_dns_block
      if [ -n "$(uci -q get openclash.config.lan_block_google_dns_ips)" ] || [ -n "$(uci -q get openclash.config.lan_block_google_dns_macs)" ]; then
         ipset create openclash_google_dns_ipv6s hash:net family inet6
         ipset add openclash_google_dns_ipv6s 2001:4860:4860::8888
         ipset add openclash_google_dns_ipv6s 2001:4860:4860::8844
         ipset add openclash_google_dns_ipv6s 2001:4860:4860::6464
         ipset add openclash_google_dns_ipv6s 2001:4860:4860::64

         ip6tables -t nat -I PREROUTING -m comment --comment "OpenClash Google DNS Block" -m set --match-set lan_block_google_dns_ipv6s src -m set --match-set openclash_google_dns_ipv6s dst -j ACCEPT
         ip6tables -t nat -I PREROUTING -m comment --comment "OpenClash Google DNS Block" -m set --match-set lan_block_google_dns_macs src -m set --match-set openclash_google_dns_ipv6s dst -j ACCEPT
         ip6tables -t filter -I FORWARD -m set --match-set lan_block_google_dns_ipv6s src -m set --match-set openclash_google_dns_ipv6s dst -j REJECT >/dev/null 2>&1
         ip6tables -t filter -I FORWARD -m set --match-set lan_block_google_dns_macs src -m set --match-set openclash_google_dns_ipv6s dst -j REJECT >/dev/null 2>&1
      fi

      #intranet allowed
      if [ "$intranet_allowed" -eq 1 ]; then
         wan6_ints=$(ip6tables-save -t filter |grep -e "-j zone_wan_input" 2>/dev/null |awk '{for (i=1;i<=NF;i++) {if ($i ~ /-i/) {print $(i+1)}}}' 2>/dev/null)
         if [ -n "$wan6_ints" ]; then
            ip6tables -t filter -N openclash_wan_input
            ip6tables -t filter -F openclash_wan_input
            for wan6_int in $wan6_ints; do
               ip6tables -t filter -I INPUT -i "$wan6_int" -m set ! --match-set localnetwork6 src -j openclash_wan_input
            done
            ip6tables -t filter -A openclash_wan_input -p udp -m multiport --dport "$proxy_port,$tproxy_port,$cn_port,$http_port,$socks_port,$mixed_port,$dns_port" -j REJECT >/dev/null 2>&1
            ip6tables -t filter -A openclash_wan_input -p tcp -m multiport --dport "$proxy_port,$tproxy_port,$cn_port,$http_port,$socks_port,$mixed_port,$dns_port" -j REJECT >/dev/null 2>&1
         else
            LOG_OUT "Warning: Can't Settting Only Intranet Allowed Function, Get IPv6 WAN Interfaces error, Please Verify The Firewall's WAN Zone Name is wan, Ignore This IF The Device Does not Have a WAN Interfaces..."
         fi
      fi
   fi
fi 2>/dev/null

#端口转发
LOG_OUT "Tip: Start Add Port Bypassing Rules For Firewall Redirect and Firewall Rules..."
config_load "firewall"
config_foreach firewall_redirect_exclude "redirect"
config_foreach firewall_rule_exclude "rule"

#Custom

if [ -f "/etc/openclash/custom/openclash_custom_firewall_rules.sh" ]; then
   chmod +x /etc/openclash/custom/openclash_custom_firewall_rules.sh >/dev/null 2>&1
   /etc/openclash/custom/openclash_custom_firewall_rules.sh >/dev/null 2>&1
fi

}

revert_firewall()
{
   rm -rf /var/etc/openclash.include >/dev/null 2>&1
   rm -rf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute_pass.conf >/dev/null 2>&1
   rm -rf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf >/dev/null 2>&1
   rm -rf ${DNSMASQ_CONF_DIR}/dnsmasq_accelerated-domains.china.conf >/dev/null 2>&1

   ip rule del fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1
   ip route del local 0.0.0.0/0 dev lo table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1

   ip -6 rule del fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1
   ip -6 route del local ::/0 dev lo table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1

   #TUN
   ip route del default dev utun table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1
   ip rule del fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1

   ip -6 route del default dev utun table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1
   ip -6 rule del fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1

   if [ -n "$FW4" ]; then
      for nft in "input" "forward" "dstnat" "srcnat" "nat_output" "mangle_prerouting" "mangle_output"; do
         local handles=$(nft -a list chain inet fw4 ${nft} |grep -E "openclash|OpenClash" |awk -F '# handle ' '{print$2}')
         for handle in $handles; do
            nft delete rule inet fw4 ${nft} handle ${handle}
         done
      done >/dev/null 2>&1

      for handle in $(nft -a list chains |grep -E "chain openclash|OpenClash" |awk -F '# handle ' '{print$2}'); do
         nft delete chain inet fw4 handle ${handle}
      done >/dev/null 2>&1

      for handle in $(nft -a list sets |grep -E "set localnetwork|china_ip|lan_ac_|wan_ac_black_|_google_dns_|common_ports" |awk -F '# handle ' '{print$2}'); do
         nft delete set inet fw4 handle ${handle}
      done >/dev/null 2>&1
   else
      for ipt in "iptables -nvL INPUT" "iptables -nvL FORWARD" "iptables -nvL POSTROUTING -t nat" "iptables -nvL OUTPUT -t nat" "iptables -nvL OUTPUT -t mangle" "iptables -nvL PREROUTING -t nat" "iptables -nvL PREROUTING -t mangle" "ip6tables -nvL PREROUTING -t mangle" "ip6tables -nvL OUTPUT -t mangle" "ip6tables -nvL PREROUTING -t nat" "ip6tables -nvL INPUT" "ip6tables -nvL POSTROUTING -t nat" "ip6tables -nvL FORWARD" "ip6tables -nvL OUTPUT -t nat"; do
         for comment in "openclash" "OpenClash"; do
            local lines=$($ipt |sed 1,2d |sed -n "/${comment}/=" 2>/dev/null |sort -rn)
            if [ -n "$lines" ]; then
               for line in $lines; do
                  $(echo "$ipt" |awk -v OFS=" " '{print $1,$4,$5}' |sed 's/[ ]*$//g') -D $(echo "$ipt" |awk '{print $3}') $line
               done
            fi
         done
      done >/dev/null 2>&1

      for chain in "openclash" "openclash_output" "openclash_post" "openclash_dns_hijack" "openclash_wan_input" "openclash_dns_redirect" "openclash_upnp"; do
         iptables -t nat -F $chain
         iptables -t nat -X $chain
         iptables -t mangle -F $chain
         iptables -t mangle -X $chain
         iptables -t filter -F $chain
         iptables -t filter -X $chain
         ip6tables -t nat -F $chain
         ip6tables -t nat -X $chain
         ip6tables -t mangle -F $chain
         ip6tables -t mangle -X $chain
         ip6tables -t filter -F $chain
         ip6tables -t filter -X $chain
      done >/dev/null 2>&1

      ipset destroy localnetwork6 >/dev/null 2>&1
      ipset destroy china_ip6_route >/dev/null 2>&1
      ipset destroy china_ip6_route_pass >/dev/null 2>&1
      ipset destroy lan_ac_white_ipv6s >/dev/null 2>&1
      ipset destroy lan_ac_black_ipv6s >/dev/null 2>&1
      ipset destroy wan_ac_black_ipv6s >/dev/null 2>&1
      ipset destroy openclash_google_dns_ipv6s >/dev/null 2>&1
      ipset destroy lan_block_google_dns_ipv6s >/dev/null 2>&1

      ipset destroy localnetwork >/dev/null 2>&1
      ipset destroy china_ip_route >/dev/null 2>&1
      ipset destroy china_ip_route_pass >/dev/null 2>&1
      ipset destroy lan_ac_white_ips >/dev/null 2>&1
      ipset destroy lan_ac_black_ips >/dev/null 2>&1
      ipset destroy lan_ac_white_macs >/dev/null 2>&1
      ipset destroy lan_ac_black_macs >/dev/null 2>&1
      ipset destroy wan_ac_black_ips >/dev/null 2>&1
      ipset destroy common_ports >/dev/null 2>&1
      ipset destroy lan_block_google_dns_ips >/dev/null 2>&1
      ipset destroy lan_block_google_dns_macs >/dev/null 2>&1
      ipset destroy openclash_google_dns_ips >/dev/null 2>&1
      ipset destroy lan_ac_black_ports >/dev/null 2>&1
   fi
}

get_config()
{
   rule_source=$(uci -q get openclash.config.rule_source)
   enable_custom_clash_rules=$(uci -q get openclash.config.enable_custom_clash_rules)
   da_password=$(uci -q get openclash.config.dashboard_password)
   cn_port=$(uci -q get openclash.config.cn_port)
   proxy_port=$(uci -q get openclash.config.proxy_port)
   tproxy_port=$(uci -q get openclash.config.tproxy_port || echo 7895)
   proxy_mode=$(uci -q get openclash.config.proxy_mode)
   ipv6_enable=$(uci -q get openclash.config.ipv6_enable)
   ipv6_dns=$(uci -q get openclash.config.ipv6_dns || echo 0)
   ipv6_mode=$(uci -q get openclash.config.ipv6_mode || echo 0)
   enable_v6_udp_proxy=$(uci -q get openclash.config.enable_v6_udp_proxy || echo 0)
   http_port=$(uci -q get openclash.config.http_port)
   socks_port=$(uci -q get openclash.config.socks_port)
   enable_redirect_dns=$(uci -q get openclash.config.enable_redirect_dns)
   if [ "$(uci -q get openclash.config.fakeip_range)"  == "0" ]; then
      fakeip_range=$(ruby_read "$CONFIG_FILE" "['dns']['fake-ip-range']")
   else
      fakeip_range=$(uci -q get openclash.config.fakeip_range)
   fi
   [ -z "$fakeip_range" ] && fakeip_range="198.18.0.1/16"
   lan_ip=$(uci -q get network.lan.ipaddr |awk -F '/' '{print $1}' 2>/dev/null || ip address show $(uci -q -p /tmp/state get network.lan.ifname || uci -q -p /tmp/state get network.lan.device) | grep -w "inet"  2>/dev/null |grep -Eo 'inet [0-9\.]+' | awk '{print $2}' || ip addr show 2>/dev/null | grep -w 'inet' | grep 'global' | grep 'brd' | grep -Eo 'inet [0-9\.]+' | awk '{print $2}' | head -n 1)
   wan_ip4s=$(/usr/share/openclash/openclash_get_network.lua "wanip" 2>/dev/null)
   wan_ip6s=$(ifconfig | grep 'inet6 addr' | awk '{print $3}' 2>/dev/null)
   disable_masq_cache=$(uci -q get openclash.config.disable_masq_cache)
   log_level=$(uci -q get openclash.config.log_level)
   intranet_allowed=$(uci -q get openclash.config.intranet_allowed)
   enable_udp_proxy=$(uci -q get openclash.config.enable_udp_proxy || echo 1)
   disable_udp_quic=$(uci -q get openclash.config.disable_udp_quic)
   operation_mode=$(uci -q get openclash.config.operation_mode)
   lan_ac_mode=$(uci -q get openclash.config.lan_ac_mode)
   enable_rule_proxy=$(uci -q get openclash.config.enable_rule_proxy)
   stack_type=$(uci -q get openclash.config.stack_type)
   stack_type_v6=$(uci -q get openclash.config.stack_type_v6 || echo "system")
   china_ip_route=$(uci -q get openclash.config.china_ip_route)
   china_ip6_route=$(uci -q get openclash.config.china_ip6_route)
   small_flash_memory=$(uci -q get openclash.config.small_flash_memory)
   mixed_port=$(uci -q get openclash.config.mixed_port)
   interface_name=$(uci -q get openclash.config.interface_name || echo 0)
   common_ports=$(uci -q get openclash.config.common_ports)
   dns_port=$(uci -q get openclash.config.dns_port)
   stream_domains_prefetch=$(uci -q get openclash.config.stream_domains_prefetch || echo 0)
   store_fakeip=$(uci -q get openclash.config.store_fakeip || echo 0)
   bypass_gateway_compatible=$(uci -q get openclash.config.bypass_gateway_compatible || echo 0)
   core_version=$(uci -q get openclash.config.core_version || echo 0)
   router_self_proxy=$(uci -q get openclash.config.router_self_proxy || echo 1)
   enable_meta_core=$(uci -q get openclash.config.enable_meta_core || echo 0)
   enable_meta_sniffer=$(uci -q get openclash.config.enable_meta_sniffer || echo 0)
   enable_meta_sniffer_custom=$(uci -q get openclash.config.enable_meta_sniffer_custom || echo 0)
   geodata_loader=$(uci -q get openclash.config.geodata_loader || echo 0)
   enable_geoip_dat=$(uci -q get openclash.config.enable_geoip_dat || echo 0)
   enable_tcp_concurrent=$(uci -q get openclash.config.enable_tcp_concurrent || echo 0)
   append_default_dns=$(uci -q get openclash.config.append_default_dns || echo 0)
   enable_meta_sniffer_pure_ip=$(uci -q get openclash.config.enable_meta_sniffer_pure_ip || echo 0)
   custom_china_domain_dns_server=$(uci -q get openclash.config.custom_china_domain_dns_server || echo "114.114.114.114")
   find_process_mode=$(uci -q get openclash.config.find_process_mode || echo 0)
   upnp_lease_file=$(uci -q get upnpd.config.upnp_lease_file)
   global_client_fingerprint=$(uci -q get openclash.config.global_client_fingerprint || echo "0")
   enable_unified_delay=$(uci -q get openclash.config.enable_unified_delay || echo "0")
   keep_alive_interval=$(uci -q get openclash.config.keep_alive_interval || echo "0")
   [ -z "$dns_port" ] && dns_port=7874 && uci -q set openclash.config.dns_port=7874
   uci -q set openclash.config.restricted_mode=0 && uci -q commit openclash
}

start()
{

   enable=$(uci -q get openclash.config.enable)
   [ "$enable" != "1" ] && LOG_OUT "Warning: OpenClash Now Disabled, Need Start From Luci Page, Exit..." && SLOG_CLEAN && del_lock && exit 0

   LOG_OUT "OpenClash Start Running..."
   config_choose
   do_run_mode

   LOG_OUT "Step 1: Get The Configuration..."
   get_config

   LOG_OUT "Step 2: Check The Components..."
   #检查文件是否存在
   do_run_file "$RAW_CONFIG_FILE" "$BACKUP_FILE"

   #快速启动判断
   check_run_quick

   if ! $quick_start; then
      LOG_OUT "Step 3: Modify The Config File..."
      config_check
      /usr/share/openclash/yml_change.sh 2>/dev/null "$en_mode" "$da_password" "$cn_port" "$proxy_port" "$TMP_CONFIG_FILE" "$ipv6_enable" "$http_port" "$socks_port" "$log_level" "$proxy_mode" "$en_mode_tun" "$stack_type" "$dns_port" "$mixed_port" "$tproxy_port" "$ipv6_dns" "$store_fakeip" "$stream_domains_prefetch" "$enable_meta_core" "$enable_meta_sniffer" "$enable_geoip_dat" "$geodata_loader" "$enable_meta_sniffer_custom" "$interface_name" "$enable_tcp_concurrent" "$core_type" "$append_default_dns" "$enable_meta_sniffer_pure_ip" "$find_process_mode" "$fakeip_range" "$global_client_fingerprint" "$ipv6_mode" "$stack_type_v6" "$enable_unified_delay" "$keep_alive_interval"
      /usr/share/openclash/yml_rules_change.sh 2>/dev/null "$rule_source" "$enable_custom_clash_rules" "$TMP_CONFIG_FILE" "$enable_rule_proxy" "$CONFIG_NAME" "$router_self_proxy" "$lan_ip" "$proxy_port" "$tproxy_port" "$enable_meta_core" "$enable_redirect_dns" "$fakeip_range" "$en_mode"
      /usr/share/openclash/openclash_custom_domain_dns.sh >/dev/null 2>&1
      #Custom overwrite
      if [ -f "/etc/openclash/custom/openclash_custom_overwrite.sh" ]; then
         chmod +x /etc/openclash/custom/openclash_custom_overwrite.sh >/dev/null 2>&1
         /etc/openclash/custom/openclash_custom_overwrite.sh 2>/dev/null "$TMP_CONFIG_FILE"
      fi
   fi

   LOG_OUT "Step 4: Start Running The Clash Core..."
   start_run_core

   LOG_OUT "Step 5: Check The Core Status..."
   check_core_status

   #检测proxy_provider配置文件状态
   LOG_OUT "Step 6: Wait For The File Downloading..."
   if [ "$enable_meta_core" != "1" ]; then
      yml_provider_check "$CONFIG_FILE" "proxy-providers" "proxies"
      yml_provider_check "$CONFIG_FILE" "rule-providers" "payload"
   fi
   try_restore_start

   LOG_OUT "Step 7: Set Firewall Rules..."
   set_firewall
   LOG_OUT "Step 8: Restart Dnsmasq..."
   change_dns "$enable_redirect_dns" "$disable_masq_cache"

   LOG_OUT "Step 9: Add Cron Rules, Start Daemons..."
   add_cron
   if [ "$(uci -q get openclash.config.restricted_mode)" != "1" ]; then
      if [ -z "$(uci -q get dhcp.lan.dhcpv6)" ] || [ "$(uci -q get dhcp.lan.dhcpv6)" == "disabled" ]; then
         LOG_OUT "OpenClash Start Successful!"
      elif [ "$ipv6_enable" -eq 0 ]; then
         LOG_OUT "Warning: OpenClash Start Successful, Please Note That Network May Abnormal With IPv6's DHCP Server"
      else
         LOG_OUT "OpenClash Start Successful!"
      fi
   else
      LOG_OUT "Warning: OpenClash Start Successful With Raw Config File, Please Note That It's Restricted Mode Now"
   fi
   echo "OpenClash Already Start!"
   write_run_quick
   SLOG_CLEAN
   rm -rf /tmp/yaml_*
}

stop()
{

   enable=$(uci -q get openclash.config.enable)

   LOG_OUT "OpenClash Stoping..."
   LOG_OUT "Step 1: Backup The Current Groups State..."
   /usr/share/openclash/openclash_history_get.sh 2>/dev/null

   LOG_OUT "Step 2: Delete OpenClash Firewall Rules..."
   revert_firewall

   LOG_OUT "Step 3: Close The OpenClash Daemons..."
   watchdog_pids=$(unify_ps_pids "openclash_watchdog.sh")
   for watchdog_pid in $watchdog_pids; do
      kill -9 "$watchdog_pid" >/dev/null 2>&1
   done >/dev/null 2>&1

   streaming_unlock_pids=$(unify_ps_pids "openclash_streaming_unlock.lua")
   for streaming_unlock_pid in $streaming_unlock_pids; do
      kill -9 "$streaming_unlock_pid" >/dev/null 2>&1
   done >/dev/null 2>&1

   openclash_pids=$(unify_ps_pids "/etc/init.d/openclash")
   for openclash_pid in $openclash_pids; do
      if [ "$openclash_pid" != "$$" ]; then
         kill -9 "$openclash_pid" >/dev/null 2>&1
      fi
   done >/dev/null 2>&1

   LOG_OUT "Step 4: Close The Clash Core Process..."
   if [ "$enable" != "1" ]; then
      kill_clash
   fi

   LOG_OUT "Step 5: Restart Dnsmasq..."
   redirect_dns=$(uci -q get openclash.config.redirect_dns)
   dnsmasq_server=$(uci -q get openclash.config.dnsmasq_server)
   dnsmasq_noresolv=$(uci -q get openclash.config.dnsmasq_noresolv)
   dnsmasq_resolvfile=$(uci -q get openclash.config.dnsmasq_resolvfile)
   cachesize_dns=$(uci -q get openclash.config.cachesize_dns)
   dnsmasq_cachesize=$(uci -q get openclash.config.dnsmasq_cachesize)
   filter_aaaa_dns=$(uci -q get openclash.config.filter_aaaa_dns)
   dnsmasq_filter_aaaa=$(uci -q get openclash.config.dnsmasq_filter_aaaa)
   default_resolvfile=$(uci -q get openclash.config.default_resolvfile)
   revert_dns "$redirect_dns" "$enable" "$default_resolvfile" "$dnsmasq_noresolv" "$dnsmasq_resolvfile" "$cachesize_dns" "$dnsmasq_cachesize" "$filter_aaaa_dns" "$dnsmasq_filter_aaaa" "$dnsmasq_server"
   /etc/init.d/dnsmasq restart >/dev/null 2>&1

   LOG_OUT "Step 6: Delete OpenClash Residue File..."
   if [ "$enable" != "1" ]; then
      rm -rf /tmp/clash_last_version >/dev/null 2>&1
      rm -rf /tmp/Proxy_Group >/dev/null 2>&1
      rm -rf /tmp/rules_name >/dev/null 2>&1
      rm -rf /tmp/rule_providers_name >/dev/null 2>&1
      rm -rf /tmp/openclash_last_version >/dev/null 2>&1
      rm -rf /tmp/openclash_config.tmp >/dev/null 2>&1
      rm -rf /tmp/openclash.change >/dev/null 2>&1
      rm -rf /tmp/openclash_debug.log >/dev/null 2>&1
      rm -rf /tmp/etc/openclash >/dev/null 2>&1
      rm -rf /tmp/openclash_edit_file_name >/dev/null 2>&1
      rm -rf /tmp/openclash_*_region >/dev/null 2>&1
      rm -rf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute_pass.conf >/dev/null 2>&1
      rm -rf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf >/dev/null 2>&1
      rm -rf ${DNSMASQ_CONF_DIR}/dnsmasq_accelerated-domains.china.conf >/dev/null 2>&1
      rm -rf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_custom_domain.conf >/dev/null 2>&1
      del_lock
      LOG_OUT "OpenClash Already Stop!"
   fi

   del_cron
   rm -rf /tmp/yaml_* >/dev/null 2>&1
   rm -rf $START_LOG >/dev/null 2>&1
   echo "OpenClash Already Stop!"
}


restart()
{
   [ -f "$LOCK_FILE" ] && LOG_OUT "Warning: Multiple Restart Scripts Running, Exit..." && SLOG_CLEAN && exit 0
   mkdir -p /tmp/lock
   touch $LOCK_FILE
   set_lock
   echo "OpenClash Restart..."
   LOG_OUT "OpenClash Restart..."
   stop
   start
   del_lock
}

reload()
{
   [ -f "$LOCK_FILE" ] && exit 0
   enable=$(uci -q get openclash.config.enable)
   if pidof clash >/dev/null && [ "$enable" == "1" ] && [ "$1" == "firewall" ]; then
      set_lock
      LOG_OUT "Reload OpenClash Firewall Rules..."
      revert_firewall 2>/dev/null
      do_run_mode 2>/dev/null
      get_config 2>/dev/null
      start_run_core
      check_core_status
      set_firewall 2>/dev/null
      /etc/init.d/dnsmasq restart >/dev/null 2>&1
      SLOG_CLEAN
      del_lock
   fi
}

boot()
{
	delay_start=$(uci -q get openclash.config.delay_start || echo 0)
	enable=$(uci -q get openclash.config.enable)
	if [ "$delay_start" -gt 0 ] && [ "$enable" == "1" ]; then
		LOG_OUT "Enable Delay Start, OpenClash Will Start After【$delay_start】Seconds..."
		sleep "$delay_start"
	fi
	restart
}
